6

On Debian Jessie, using php5.6 and telnet version:

$ dpkg -l | grep telnet
ii  telnet                         0.17-36                      amd64        The telnet client

I have written a php script to listen on port 23 for incoming tcp connections. For testing, I telnet into it, however I have noticed that it actually makes a difference wither I telnet into it like this:

$ telnet localhost 23

vs like this:

$ telnet localhost

But according to man telnet, it should not make a difference:

port Specifies a port number or service name to contact. If not specified, the telnet port (23) is used.

If I do not specify the port, then I get some weird noise on the line. Or maybe its not noise? But if I do specify the port then I do not get this noise on the line. The noise is the following set of ascii characters:

<FF><FD><03><FF><FB><18><FF><FB><1F><FF><FB><20><FF><FB><21><FF><FB><22><FF><FB><27><FF><FD><05>

And just in case this is due to a bug in my server-side code, here is a cut down version of the script, which does exhibit the noise (though I don't think there are any bugs in the code, I just include this because someone is bound to ask):

#!/usr/bin/php
<?php

set_time_limit(0); // infinite execution time for this script
define("LISTEN_ADDRESS", "127.0.0.1");

$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 30, 'usec' => 0)); // timeout after 30 sec
socket_bind($sock, LISTEN_ADDRESS, 23); // port = 23
socket_listen($sock);
echo "waiting for a client to connect...\n";

// accept incoming requests and handle them as child processes
// block for 30 seconds or until there is a connection.
$client = socket_accept($sock); //get the handle to this client
echo "got a connection. client handle is $client\n";

$raw_data = socket_read($client, 1024);
$human_readable_data = human_str($raw_data);
echo "raw data: [$raw_data], human readable data: [$human_readable_data]\n";

echo "closing the connection\n";
socket_close($client);
socket_close($sock);

function human_str($str)
{
    $strlen = strlen($str);
    $new_str = ""; // init
    for($i = 0; $i < $strlen; $i++)
    {
        $new_str .= sprintf("<%02X>", ord($str[$i]));
    }
    return $new_str;
}

?>

And the output from the script (from connecting like so: telnet localhost) is:

waiting for a client to connect...
got a connection. client handle is Resource id #5
raw data: [�������� ��!��"��'��], human readable data: [<FF><FD><03><FF><FB><18><FF><FB><1F><FF><FB><20><FF><FB><21><FF><FB><22><FF><FB><27><FF><FD><05>]
closing the connection

But when connecting like telnet localhost 23 (and issuing the word hi) the output is:

waiting for a client to connect...
got a connection. client handle is Resource id #5
raw data: [hi
], human readable data: [<68><69><0D><0A>]
closing the connection

So my question is whether this is expected behavior from the telnet client, or whether this is noise? It is very consistent - its always the same data - so it could be some kind of handshake?

Here is the "noise" string again with spaces and without spaces, in case its more useful:

FFFD03FFFB18FFFB1FFFFB20FFFB21FFFB22FFFB27FFFD05
FF FD 03 FF FB 18 FF FB 1F FF FB 20 FF FB 21 FF FB 22 FF FB 27 FF FD 05
  • 2
    Are you trying to implement the telnet protocol or not? – David Schwartz Apr 4 '17 at 13:58
  • 2
    @EJP The fact that telnet is a protocol and not just raw TCP is not all that well-known anymore. To be quite honest, I was surprised to learn that myself, 'way back in 1995; I'd first encountered telnet, the command, as a debugging utility for SMTP! – zwol Apr 4 '17 at 14:35
  • @zwol: For this very reason I never use telnet to debug network protocols. Over the years I've written and re-written several raw tcp chat utilities (didn't we all write one when learning network programming?). My current go-to tool is github.com/slebetman/tcpchat because it's the one where I've implemented both client and server modes – slebetman Apr 4 '17 at 15:18
  • 2
    IAC DO SUPPRESS-GO-AHEAD; IAC WILL TERMINAL-TYPE; IAC WILL NAWS; IAC WILL TERMINAL-SPEED; IAC WILL TOGGLE-FLOW-CONTROL; IAC WILL LINEMODE; IAC WILL NEW-ENVIRON; IAC DO STATUS – hobbs Apr 4 '17 at 18:19
39

telnet is not netcat. The telnet protocol is more than raw TCP. Among other things it can have a number of options, and the "noise" you're seeing is the negotiation of these options between your client and the server. When you specify a port you don't see any noise because according to the manual:

When connecting to a non-standard port, telnet omits any automatic initiation of TELNET options. When the port number is preceded by a minus sign, the initial option negotiation is done.

So apparently your implementation of telnet disables option negotiation when you specify a port (even when the port is 23), and re-enables it when the port is preceded by a minus sign.

On a more general note, it's generally safe to forget about telnet these days. Use netcat instead if you need a simple plain TCP client (or server, for that matter).

  • 1
    A lot of people fail to realise that telnet is a sophisticated protocol – slebetman Apr 4 '17 at 15:15
  • 1
    It's one of the few protocols that use TCP urgent data. – Simon Richter Apr 4 '17 at 16:03
7

It is highly probable that your telnet command initiates a TELNET session if you don't specify any port, and initiates a raw TCP connection if any port specified.

telnet was originally designed to let distant users log into a system. So the protocol (see RFC 854 - first version of it) is designed such that telnet client negotiates different things with the server just after the connection has been initiated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.