Once in a while it is useful to dismiss abstractions and layers that makes daily routines easier and take the raw approach. Like when debugging a software problem that doesn’t make sense, it is nice to see the underlying basic stuff is behaving nicely, to better be able to locate where the unexpected occurs.
In the IP world of the internet, the swiss army knife for debugging interprocess communications in a totally protocol agnostic way is called ‘telnet’. Telnet opens up a communication channel between your local computer and a daemon/server on a specific port on a specific IP address. Then it gets out of the way for you to talk directly to the daemon in clear text.
Knowledge of how to interact using a specific protocol can be very useful to check server availability and functionality. All common protocols in use on the internet (like DNS, HTTP, SMTP, POP3, IMAP, XMPP etc.) can be debugged like this, because all of them transfers data in clear text (or at least initiates other transfer types from a clear text session). Full specifications for the HTTP protocol can be found in IETF RFC2616. I keep forgetting this, and end up digging around for it when needed, therefore this blog post.
Interactively using Telnet
Below is a basic HTTP session to my web server www.mikini.dk using telnet on the command line.
Red text is local text input by me. Blue text is local text by telnet application. Green text is server response.
$ telnet www.mikini.dk 80
Trying 92.61.152.47…
Connected to 92-61-152-47.static.servage.net.
Escape character is ‘^]’.
GET /index.php/2010/06 HTTP/1.1
Host: www.mikini.dk
HTTP/1.1 200 OK
Date: Wed, 21 Jul 2010 09:19:13 GMT
Server: Apache
X-Pingback: http://www.mikini.dk/xmlrpc.php
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
2bd2
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd“>
<… remainder of HTML document dropped …>
We are asking the server at www.mikini.dk port 80 (default http port) for the document at path /index.php/2010/06 (“GET /index.php/2010/06”). Notice the two CRLF characters after the Host header field, this indicates to the server that the request header is done, and that it should begin parsing header and send its response. Also notice that even though you tell the telnet program on the commandline that you want to access www.mikini.dk, you have to tell it again to the server in th HTTP Host field. Thats because telnet is only concerned about the IP address of the server, it resolves www.mikini.dk to the IP 92.61.152.47 through DNS and forgets about it. From the servers point of view, it needs to know which of its virtual hosts you want to talk to, cause one server application on one port on one ip can potentially host thousands of separate websites (virtual hosts).
One-liner using netcat (nc)
Below is the same session using nc (netcat) as a one-liner (wow, old PHP at Hostinger, better get that move to a self-administered box going).
$ echo -ne "GET /index.php/2010/06 HTTP/1.1\r\nHost:www.mikini.dk\r\n\r\n"|nc www.mikini.dk 80 | head -10
HTTP/1.1 200 OK
Date: Thu, 05 Jul 2018 16:30:07 GMT
Server: Apache
X-Powered-By: PHP/5.5.35
Link: <http://www.mikini.dk/wp-json/>; rel="https://api.w.org/"
Content-Length: 32356
Content-Type: text/html; charset=UTF-8
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
$
2018-07-05: nc command line added