Troubleshooting with Telnet
Poor telnet, it used to be the cool kid on the block. It was the program all sysadmins turned to when they needed to connect to a remote server. Telnet just wasn't that good at keeping a secret—all communication went over plain text—so administrators started switching to SSH for encrypted remote shell sessions. Of course, along with the switch came a huge stigma against administrators who still used telnet. Eventually, telnet became an outcast—the program you used if you were an out-of-touch old-timer who didn't care about security.
I for one think telnet isn't all bad. Sure, it can't keep a secret, but it still can do a lot of useful things around the server room. Really, telnet just provides you a convenient way to connect to a network port and send commands. Telnet can work well to diagnose problems with one of the many services out there that still accept plain-text commands in their protocol. In fact, it's one of my go-to command-line programs when I'm troubleshooting. In this column, I'm going to give telnet a second chance and describe how to use it to perform some common troubleshooting tasks.
Test Remote Ports
There are many different ways to test whether a network port is listening on a system, including GUI port scanners, Nmap and nc. Although all of those can work well, and even I find myself using Nmap more often than not, not all machines end up having Nmap installed. Just about every system includes telnet though, including a lot of embedded systems with BusyBox environments. So if I wanted to test whether the SMTP port (port 25) was listening on a server with the IP 192.168.5.5, I could type:
$ telnet 192.168.5.5 25 Trying 192.168.5.5... telnet: Unable to connect to remote host: Connection refused
In this case, the remote port is unavailable, so I would fall back to some other troubleshooting methods to figure out why. If the port were open and available though, I could just start typing SMTP commands (more on that later).
As you can see from the above example, the syntax is to type the command
telnet, the IP or hostname to connect to, and the remote port (otherwise it
will default to port 23—the default port for telnet). So if I wanted to
test a Web server instead, I would connect to the HTTP port (port 80):
$ telnet www.example.net 80
Troubleshoot Web Servers
While you are connecting to port 80, you might as well actually throw some HTTP commands at it and test that it works. For starters, you want to make sure you actually are connected:
$ telnet www.example.net 80 Trying 192.168.5.5... Connected to www.example.net. Escape character is '^]'.
Once you are connected, you can pass a basic HTTP GET request to ask for the default index page followed by the host you want to connect to:
GET / HTTP/1.1 host: www.example.net
The GET request specifies which page (/) along with what protocol you will use (HTTP/1.1). Since these days most Web servers end up hosting multiple virtual hosts from the same port, you can use the host command so the Web server knows which virtual host to direct you to. If you wanted to load some other Web page, you could replace GET / with, say, GET /forum/. It's possible your connection will time out if you don't type it in fast enough—if that happens, you always can copy and paste the command instead. After you type your commands, press Enter one final time, and you'll get a lot of headers you don't normally see along with the actual HTML content:
HTTP/1.1 200 OK Date: Tue, 10 Jul 2012 04:54:04 GMT Server: Apache/2.2.14 (Ubuntu) Last-Modified: Mon, 24 May 2010 21:33:10 GMT ETag: "38111c-b1-4875dc9938880" Accept-Ranges: bytes Content-Length: 177 Vary: Accept-Encoding Content-Type: text/html X-Pad: avoid browser bug <html><body><h1>It works!</h1> <p>This is the default web page for this server.</p> <p>The web server software is running but no content has been added, yet.</p> </body></html>
As you can see from my output, this is just the default Apache Web server
page, but in this case, the HTML output is only one part of the equation.
Equally useful in this output are all of the headers you get back from the
HTTP/1.1 200 OK reply code to the modification dates on the Web page, to the
Apache server version. After you are done sending commands, just press Ctrl-]
and Enter to get back to a telnet prompt, then type
quit to exit telnet.
I usually just use telnet to do some basic HTTP troubleshooting, because once you get into the realm of authentication, following redirects and other more complicated parts of the protocol, it's much simpler to use a command-line tool like curl, or I guess if you have to, even a regular GUI Web browser.
Send an E-mail
Although I just use telnet for basic Web server troubleshooting, telnet ends up being my preferred tool for e-mail troubleshooting, mostly because it's so simple to send a complete e-mail with only a few telnet commands.
The first step is to initiate a telnet connection with the mail server you want to test on port 25:
$ telnet mail.example.net 25 Trying 192.168.5.5... Connected to mail.example.net. Escape character is '^]'. 220 mail.example.net ESMTP Postfix
Unlike the blank prompt you may get when you connect to an HTTP server, with
SMTP, you should get an immediate reply back. In this case, the reply is
telling me I'm connecting to a Postfix server. Once I get that 220 prompt, I
can start typing SMTP commands, starting with the
HELO command that lets me
tell the mail server what server is connecting to it:
HELO lappy486.example.net 250 mail.example.net
The nice thing about the interactive SMTP connection here is that if
I do somehow make a typo in a command or make a mistake, it should let me
know; otherwise, I should get a 250 reply. After HELO, you use the
command to list what e-mail address the e-mail should appear to be from. I say
appear to be from, because you can put just about any e-mail address you want
here, which is a good reason not to blindly trust FROM addresses:
MAIL FROM: <firstname.lastname@example.org> 250 Ok
In the past, I used to type in the e-mail address directly without
surrounding it with <>. My personal Postfix servers are fine with this, but
other mail servers are more strict and will reply with a syntax error if you
don't surround the e-mail address with <>. Since this FROM address was
accepted, you can follow up with
RCPT TO: and specify
who the e-mail is
RCPT TO: <email@example.com> 250 Ok
The fact that the mail server responded with 250 should mean that it
accepted the TO address you specified here. Finally, you can type
type the rest of your e-mail, including any extra headers you want to add, like
Subject, then finish up with a single period on its own line:
DATA 354 End data with <CR><LF>.<CR><LF> Subject: Give Telnet a Chance 1 Hi, All we are saying is give telnet a chance. . 250 Ok: queued as 52A1EE3D117
When I'm testing e-mails with telnet, I usually put a number in the subject line so I can continually increment it with each test. This way, if some e-mail messages don't get delivered, I can tell which ones went through and which ones didn't.
Once you are done with the DATA section and the e-mail is queued, you can
quit to exit:
quit 221 Bye Connection closed by foreign host.
Now that you have some ways to troubleshoot with telnet, hopefully you won't relegate telnet to the junk drawer of your Linux systems. Sure, you may not want to use it for remote shells, but now that just about everyone uses SSH anyway, maybe you can break out telnet on your terminal for all of your other plain-text network needs without your friends scolding you.
Computer network image via Shutterstock.com
Kyle Rankin is a VP of engineering operations at Final, Inc., the author of a number of books including DevOps Troubleshooting and The Official Ubuntu Server Book, and is a columnist for Linux Journal. Follow him @kylerankin.