Monday
Jul132009

DNS Primer

The purpose of DNS (Domain Name System) is to function as a lookup service mapping readable domain names such as solidosystems.com to IP addresses such as 91.102.90.14. DNS is one of the earliest technologies of the internet, dating back to 1983. Unlike the SMTP protocol we looked at in the previous blog post, DNS is in no way a readable protocol that can be manipulated by hand. All examples in this little DNS tutorial will thus use an application to interface with the DNS system. We will use dig which is part of most UNIX systems today, but you can use any tool available on your platform.

Lets start out by looking up the domain for this web site solidosystems.com. Using dig, we do this simply by executing "dig solidosystems.com". The following is what this looked like on my machine. Depending on the version of dig installed on your system, you might get a slightly different output, but the primary information should be the same.

> dig solidosystems.com

; <<>> DiG 9.4.1-P1 <<>> solidosystems.com
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16964
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2

;; QUESTION SECTION:
;solidosystems.com.     IN  A

;; ANSWER SECTION:
solidosystems.com.  13888   IN  A   91.102.90.14

;; AUTHORITY SECTION:
solidosystems.com.  10552   IN  NS  ns001.dnspilot.com.
solidosystems.com.  10552   IN  NS  ns002.dnspilot.com.

;; ADDITIONAL SECTION:
ns001.dnspilot.com. 167941  IN  A   217.116.236.67
ns002.dnspilot.com. 153410  IN  A   217.116.236.68

;; Query time: 125 msec
;; SERVER: 194.239.134.83#53(194.239.134.83)
;; WHEN: Mon Jan  7 10:26:48 2008
;; MSG SIZE  rcvd: 132

If this is the first time you see the output of dig, it might look slightly overwhelming, but once you know what you are looking for, it's actually pretty simple. First of all, all lines starting with a semicolon are comments (depending on your version of dig, they might start with a hash instead). Next, the part you really want to look at, is the single line after the comment ";; ANSWER SECTION:". That's the actually answer to our query. Let's have a closer look at that.

solidosystems.com.  13888   IN  A   91.102.90.14

The first part is pretty obvious. That's the domain we wanted the IP for. The next part is a number. It is the TTL (time to live) of the response we got. That is, the number of seconds we are allowed to remember this answer for before we have to look it up again. Some times, the TTL will be delivered in a format such as 2d, meaning two days. The next part "IN" tells us the class of the record (don't worry about this, IN is basically the value you will see every time). The next part "A" tells us that the record we looked up is an A record. This is the most basic type of record which always points from a hostname such as solidosystems.com to an IP address such as 91.102.90.14. There are many other record types. We will look at the most commonly used later in this post.

So how exactly did this lookup work? Typically, your machine will have one or more DNS servers configured, which it will contact for all queries. So all dig really does, is contacting your server and asking it for the result of the query. In the output above, you can see the server that was contacted in my query "194.239.134.83". This server will be the one that does the actual work.

The first thing it will do is to contact the root DNS server to ask which DNS server it can contact to ask questions about .com. Then it will ask that server which server it can contact to ask questions about solidosystems. Finally it will ask that server the actual question. Each of these questions will be formed as a regular DNS query, just like our solidosystems.com query. It might seem like a lot of work to do every single time, but in reality, the root servers responsible for the top level domains, such as .com, .net and .org change very seldom. The response our DNS server got for the question about who to ask for .com questions will thus have a very long TTL. This means that in reality, all it had to do was ask that server which DNS server is responsible for solidosystems.com. That answer was actually part of the result we got back, under the section titled ";; AUTHORITY SECTION:".

;; AUTHORITY SECTION:
solidosystems.com.  10552   IN  NS  ns001.dnspilot.com.
solidosystems.com.  10552   IN  NS  ns002.dnspilot.com.

We could actually contact one of these servers directly for the answer to our query by issuing the following command "dig @ns001.dnspilot.com solidosystems.com". However, the whole idea behind the recursive nature of the DNS architecture is that you don't need to know which server to ask to get an answer for your query. All you need is the root server.

I mentioned previously that there are several different types of records. The most commonly used are A, CNAME, MX and NS. Each of these will be discussed separately in the following subsections.

NS Records

These are the records that make it all possible. Have a look at the authority section in the previous example. The NS records are the ones who tells us which name servers we can contact for queries about a given domain. That is in fact what NS stands for - Name Server. You don't really need to know much more about NS records unless you need to configure domains for yourself by writing zone files (more about this in a later post).

A Records

As mentioned in our example, an A record is a record that points from a hostname to an IP. A stands for Address. A domain can have more than one A record with the same hostname pointing to different IP's as well as more than one hostname pointing to the same IP.

CNAME Records

CNAME records are an alias from one record to another. Let's have a quick look at another query for a CNAME record. In this example, we will look up www.solidosystems.com.

> dig www.solidosystems.com

; <<>> DiG 9.4.1-P1 <<>> www.solidosystems.com
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5103
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 2

;; QUESTION SECTION:
;www.solidosystems.com.     IN  A

;; ANSWER SECTION:
www.solidosystems.com.  14400   IN  CNAME   solidosystems.com.
solidosystems.com.  10841   IN  A   91.102.90.14

;; AUTHORITY SECTION:
solidosystems.com.  7505    IN  NS  ns002.dnspilot.com.
solidosystems.com.  7505    IN  NS  ns001.dnspilot.com.

;; ADDITIONAL SECTION:
ns001.dnspilot.com. 164894  IN  A   217.116.236.67
ns002.dnspilot.com. 150363  IN  A   217.116.236.68

;; Query time: 77 msec
;; SERVER: 194.239.134.83#53(194.239.134.83)
;; WHEN: Mon Jan  7 11:17:34 2008
;; MSG SIZE  rcvd: 150

Just as in the previous query, the result we are looking for will be in the answer section. In this case, we got two records as part of our result. The first tells us that www.solidosystems.com is a CNAME record that points to the record solidosystems.com. The second part of the answer, is simply the result of looking up the solidosystems.com record.

A CNAME record may also point to another CNAME record, or even to a record on a different domain.

MX Records

The MX record type is a newer addition to the DNS system than the other records we have looked at. MX stands for mail exchange. These records are used to specify which servers you should try when delivering email to a domain. Lets have a look at an example, once again looking up records for solidosystems.com. To do this with dig, we simply specify the record type mx after the domain name.

> dig solidosystems.com mx
; <<>> DiG 9.4.1-P1 <<>> solidosystems.com mx
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29755
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 6

;; QUESTION SECTION:
;solidosystems.com.     IN  MX

;; ANSWER SECTION:
solidosystems.com.  14400   IN  MX  20 frontend02.mailsafe.dk.
solidosystems.com.  14400   IN  MX  10 frontend01.mailsafe.dk.

;; AUTHORITY SECTION:
solidosystems.com.  8986    IN  NS  ns002.dnspilot.com.
solidosystems.com.  8986    IN  NS  ns001.dnspilot.com.

;; ADDITIONAL SECTION:
frontend02.mailsafe.dk. 888 IN  A   217.116.236.14
frontend02.mailsafe.dk. 888 IN  A   217.116.236.188
frontend01.mailsafe.dk. 93  IN  A   217.116.236.12
frontend01.mailsafe.dk. 93  IN  A   217.116.236.189
ns001.dnspilot.com. 146062  IN  A   217.116.236.67
ns002.dnspilot.com. 146062  IN  A   217.116.236.68

;; Query time: 72 msec
;; SERVER: 194.239.134.83#53(194.239.134.83)
;; WHEN: Mon Jan  7 11:29:39 2008
;; MSG SIZE  rcvd: 245

As usual, we need to look in the answer section for the result of our query. This time, we got two records on another domain. Notice how each of them has an additional piece of numeric data... 20 and 10. These are the priorities of the MX records. A domain can have any number of MX records. It can even have more than one with the same priority.

When you wish to deliver email for a specific domain, you look up all the mx records for the domain and sort them by priority. Then you attempt to contact the servers starting at the lowest priority. If two records have the same priority you try one of them at random. The reason for this added complexity is to allow for an easy configuration of mail server redundancy.

That's about it for now... it might seem a bit daunting if you haven't read anything about DNS before, but at least you should now know what the primary record types are and how to look them up manually using dig.

Monday
Jul132009

SMTP Primer

The SMTP protocol (Simple Mail Transfer Protocol) is a text based protocol used to transport email between servers as well as between clients and servers. SMTP is a fairly old standard dating all the way back to 1982, in some ways it makes it a messy standard because we have had the need to patch it up with modern extensions several times since then, but it also makes it a very simple easy to understand protocol. This small SMTP tutorial will teach you how to communicate with SMTP servers by hand. It's not something you want to do daily, but it will give you the knowledge necessary to test an SMTP server by hand.

In theory, you can use any port for the SMTP protocol, but the standard port, and thus the one all public SMTP servers will listen to is 25. So to communicate with an SMTP service, we open a socket to it on port 25. Lets have a look at an example right now and then discuss the individual parts afterwards.

> telnet frontend01.mailsafe.dk 25
Trying 217.116.236.189...
Connected to frontend01a.mailsafe.dk.
Escape character is '^]'.

220 frontend01a.mailsafe.dk
HELO localhost
250 frontend01a.mailsafe.dk
MAIL FROM: <kjj@solidosystems.com>
250 OK
RCPT TO: <khl@solidosystems.com>
250 OK
DATA
354 Send the mail data, end with .
Subject: Hand written SMTP

Hi Kasper, Just testing an SMTP connection.
.
250 OK
QUIT
221

The first thing that happens once we connect, is that the server we have connected to greets us with 220 frontend01a.mailsafe.dk. The first part of the response is a number. 220 in this case, which simply means that it is ready to handle our connection. The second part is the name of the server. This is not strictly required by the standard, which means you can't rely on the data following the number to be in any kind of consistent format.

We respond to this with HELO localhost. HELO basically means hi, and localhost is our hostname. It is very important that you either use localhost for this or the correct hostname for your machine. If not, some servers will refuse any further communications from you. If the server accepts our greeting, it will respond with 250. You might have noticed that the server actually gave its full hostname after the numeric code. Most SMTP servers will do this, but there is no required format for the data given along with a response code, so you can't rely on it. The only thing that is clearly defined is the actual numeric code.

Once we have finished greeting each other, we can proceed with the actual mail sending part of the protocol. This is usually called the envelope. We initiate the sending of a new mail, by specifying that we have a new mail and who it is from, in the above example, we did that with MAIL FROM: <kjj@solidosystems.com>. Once again the server responds with 250 if it chooses to accept the from address.

If the server accepted our from address, we can start giving it recipient addresses. You can give several recipients in one go if you intend to send exactly the same email to all of them. You give each recipient by a separate line in the form of RCPT TO: <khl@solidosystems.com>. Once again, if the server accepts your recipient, it will respond with the code 250. If you try to give a recipient that is not local to the server you have connected to, it will typically reply with 550 No such user. An exception to this is if the server is a relay host which you have specifically been granted the right to relay through. In that case, it will most likely accept any valid email addresses. Finally, there is a possibility that you will get a 421 response. It used to be that those were given purely if the server was too busy or if the user had been temporarily suspended, but now it is far more often used for grey listing purposes. We will talk more about grey listing in a future post.

Once you have given the server your sender and the recipients for your email, its time to give it the actual data you intend to deliver. We do this by issuing the DATA command. If the server is ready to receive data, it will respond with 354. At this point, we are expected to start feeding the server with the actual content of our email, ending with a single "." and a line feed. If the server accepts the mail, it will respond with 250 and the email will be on its way to its recipient. After that, we can issue a QUIT command and close the connection.

Now for a final word about return codes. All return codes used in the SMTP protocol are 3 digit numbers. There is a meaning to each of the digits, but the primary thing you need to remember is the meaning of the first digit. 2 is for things that went well, 4 is for temporary errors and 5 is for permanent errors.

Thats it, the next time you have problems SMTP related problems you now know how to open a terminal and do a bit of testing by hand.