分类: 系统运维
2012-06-20 11:50:13
Two popular applications provide remote login across TCP/IP internets.
1.
Telnet is a standard application that almost every TCP/IP
implementation provides. It works between hosts that use different
operating systems. Telnet uses option negotiation between the client and
server to determine what features each end can provide.
2.
Rlogin is from Berkeley Unix and was developed to work between Unix
systems only, but it has been ported to other operating systems also.
Remote login uses the client-server paradigm. There are numerous points:
1.
The Telnet client interacts with both the user at the terminal and the
TCP/IP protocols. Normally everything we type is sent across the TCP
connection, and everything received from the connection is output to our
terminal.
2. The Telnet server often deals with what's called a pseudo-terminal device, at least under Unix systems. This makes it appear to the login shell that's invoked on the server, and to any programs run by the login shell, that they're talking to a terminal device. Some applications, such as full-screen editors, assume they're talking to a terminal device. Indeed, making the login shell on the server think that it's talking to a terminal is often one of the hardest programming aspects involved in writing a remote login server.
3.
Only a single TCP connection is used. Since there are times when the
Telnet client must talk to the Telnet server (and vice versa) there
needs to be some way to delineate commands that are sent across the
connection, versus user data. We'll see how both Telnet and Rlogin
handle this.
4. The terminal and pseudoterminal drivers, along
with the TCP/IP implementation, are normally part of the operating
system kernel. The Telnet client and server, however, are often user
applications.
5. We show the login shell on the server host to
reiterate that we have to login to the server. We must have an account
on that system to login to it, using either Telnet or Rlogin.
It
is the continuing addition of new options to Telnet that causes its
implementation to grow, while Rlogin remains simple and stable.
Remote
login is not a high-volume data transfer application. As we've
mentioned earlier, lots of small packets are normally exchanged between
the two end systems. [Paxson 1993] found that the ratio of bytes sent by
the client (the user typing at the terminal) to the number of bytes
sent back by the server is about 1:20. This is because we type short
commands that often generate lots of output.
Rlogin Protocol
Rlogin
appeared with 4.2BSD and was intended for remote login only between
Unix hosts. This makes it a simpler protocol than Telnet, since option
negotiation is not required when the operating system on the client and
server are known in advance. Over the past few years, Rlogin has also
been ported to several non-Unix environments.
Application Startup
Rlogin
uses a single TCP connection between the client and server. After the
normal TCP connection establishment is complete, the following
application protocol takes place between the client and server.
1.
The client writes four strings to the server; (a) a byte of 0, (b) the
login name of the user on the client host, terminated by a byte of 0,
(c) the login name of the user on the server host, terminated by a byte
of 0, (d) the name of the user's terminal type, followed by a slash,
followed by the terminal speed, terminated by a byte of 0. Two login
names are required because users aren't required to have the same login
name on each system. The terminal type is passed from the client to the
server because many full-screen applications need to know it. The
terminal speed is passed because some applications operate differently
depending on the speed. For example, the vi editor works with a smaller
window when operating at slower speeds, so it doesn't take forever to
redraw the window.
2. The server responds with a byte of 0.
3. The server has the option of asking the user to enter a password. This is handled as normal data exchange across the Rlogin connection-there is no special protocol. The server sends a string to the client (which the client displays on the terminal), often Password:. If the client does not enter a password within some time limit (often 60 seconds), the server closes the connection.
We can create a file in our home
directory on the server (named .rhosts) with lines containing a hostname
and our username. If we login from the specified host with that
username, we are not prompted for a password. Most security texts, such
as [Curry 1992], strongly suggest never using this feature because of
the security hole it presents.
If we are prompted by the
server for a password, what we type is sent to the server as cleartext.
Each character of the password that we type is sent as is. Anyone who
can read the raw network packets can read the characters of our
password. Newer implementations of the Rlogin client, such as 4.4BSD,
first try to use Kerberos, which avoids sending cleartext passwords
across the network. This requires a compatible server that also supports
Kerberos. ([Curry 1992] describes Kerberos in more detail.)
4. The server normally sends a request to the client asking for the terminal's window size (described later).
The
client sends 1 byte at a time to the server and all echoing is done by
the server. Also, the Nagle algorithm is normally enabled, causing
multiple input bytes to be sent as a single TCP segment across slower
networks. The operation is simple: everything typed by the user is sent
to the server, and everything sent by the server to the client is
displayed on the terminal.
Additional commands exist that can be sent from the client to the server and from the server to the client.
Flow Control
By
default, flow control is done by the Rlogin client. The client
recognizes the ASCII STOP and START characters (Control-S and Control-Q)
typed by the user, and stops or starts the terminal output.
If
this isn't done, each time we type Control-S to stop the terminal
output, the Control-S character is sent across the network to the
server, and the server stops writing to the network-but up to a window's
worth of output may have been already written by the server and will be
displayed before the output is stopped. Hundreds or thousands of bytes
of data will scroll down the screen before the output stops.
To an interactive user this delayed response to the Control-S character is bad.
Sometimes,
however, the application running on the server needs to interpret each
byte of input, and doesn't want the client looking at the input bytes
and treating Control-S and Control-Q specially. (The emacs editor is an
example of an application that uses these two characters for its own
commands.) To handle this, the capability is provided for the server to
tell the client whether or not to perform flow control.
Client Interrupt
A
problem similar to flow control occurs when we type the interrupt key
(often DELETE or Control-C), to abort the process currently running on
the server.
We want the interrupt key to terminate what's being displayed on the screen as quickly as possible.
In
both this case and the flow control scenario, it is rare for the flow
of data from the client to the server to be stopped by flow control.
This direction contains only characters that we type. Therefore it is
not necessary for these special input characters (Control-S or
interrupt) to be sent from the client to the server using TCP's urgent
mode.
Window Size Changes
With
a windowed display we can dynamically change the size of the window
while an application is running. Some applications (typically those that
manipulate the entire window, such as a full-screen editor) need to
know these changes. Most current Unix systems provide the capability for
an application to be told of these window size changes.
With
remote login, however, the change in the window size occurs on the
client, but the application that needs to be told is running on the
server. Some form of notification is required for the Rlogin client to
tell the server that the window size has changed, and what the new size
is.
Server to Client Commands
We
can now summarize the four commands that the Rlogin server can send to
the client across the TCP connection. The problem is that only a single
TCP connection is used, so the server needs to mark these command bytes
so the client knows to interpret them as commands, and not display the
bytes on the terminal. TCP's urgent mode is used for this.
When
the server sends a command to the client, the server enters urgent mode
with the last byte of urgent data being the command byte from the
server. When the client receives the urgent mode notification, it reads
from the connection, saving the data until the command byte (the last
byte of urgent data) is encountered. The data that's saved by the client
can be displayed on the terminal, or discarded, depending on the
command.
The four command bytes:
Byte | Description |
0x02 | Flush output. The client discards all the data received from the server, up through the command byte (the last byte of urgent data). The client also discards any pending terminal output that may be buffered. The server sends this command when it receives the interrupt key from the client. |
0x10 | The client stops performing flow control. |
0x20 | The client resumes flow control processing. |
0x80 | The client responds immediately by sending the current window size to the server, and notifies the server in the future if the window size changes. This command is normally sent by the server immediately after the connection is established. |
1. A period terminates the client.
2. The end-of-file character (often Control-D) terminates the client.
3. The job control suspend character (often Control-Z) suspends the client.
4.
The job-control delayed-suspend character (often Control-Y) suspends
only the client input. Everything we type is now interpreted by whatever
program we run on the client host, but anything sent to the Rlogin
client by the Rlogin server is output to our terminal. This can be used
when we start a long running job on the server and we want to know when
it outputs something, but we want to continue running other programs on
the client.
The last two commands are supported only if the client Unix system supports job control.
Client Interrupt Key
The following points summarize the state of the client, the server, and the connection.
1. We stop the terminal output by typing Control-S.
2. The Rlogin client is blocked from writing to the terminal, since the terminal's output buffer will fill.
3. The Rlogin client therefore cannot read from the network, so the client's TCP receive buffer fills.
4. The client's TCP advertises a window of 0 to stop the sender (the Rlogin server's TCP) when the receive buffer fills.
5. The server's TCP send buffer fills when its output is stopped by the client's window of 0.
6.
The Rlogin server is stopped, since the send buffer is full. Therefore,
the Rlogin server cannot read from the application that's running on
the server (cat).
7. The cat application stops when its output buffer fills.
8.
We then type the interrupt key to terminate the cat application on the
server. This is sent from the client TCP to the server TCP because this
direction of data flow has not been flow-control stopped.
9. The cat
application receives the interrupt, and terminates. This causes its
output buffer (which the Rlogin server is reading) to be flushed, which
wakes up the Rlogin server. The Rlogin server then enters urgent mode
and sends the "flush output" command (0x02) to the client.
Telnet Protocol
Telnet
was designed to work between any host (i.e., any operating system) and
any terminal. Its specification in RFC 854 [Postel and Reynolds 1983a]
defines the lowest common denominator terminal, called the network
virtual terminal (NVT). The NVT is an imaginary device from which both
ends of the connection, the client and server, map their real terminal
to and from. That is, the client operating system must map whatever type
of terminal the user is on to the NVT. The server must then map the NVT
into hatever terminal type the server supports.
The NVT is a
character device with a keyboard and printer. Data typed by the user on
the keyboard is sent to the server, and data received from the server
is output to the printer. By default the client echoes what the user
types to the printer, but we'll see that options are normally supported
to change this.
NVT ASCII
The
term NVT ASCII refers to the 7-bit U.S. variant of the ASCII character
set used throughout the Internet protocol suite. Each 7-bit character is
sent as an 8-bit byte, with the high-order bit set to 0.
An end-of-line is transmitted as the 2-character sequence CR (carriage return) followed by an LF (linefeed). We show this as \r\n. A carriage return is transmitted as the 2-character sequence CR followed by a NUL (byte of 0). We show this as \r\0.
FTP, SMTP, Finger, and Whois all use NVT ASCII for client commands and server responses.
Telnet Commands
Telnet
uses in-band signaling in both directions. The byte 0xff (255 decimal)
is called IAC, for "interpret as command." The next byte is the command
byte. To send the data byte 255, two consecutive bytes of 255 are sent.
(In the previous paragraph we said that the data stream is NVT ASCII,
which are 7-bit values, implying a data byte of 255 cannot be sent by
Telnet. There is a binary option for Telnet, RFC 856 [Postel and
Reynolds 1983b], which we don't discuss, that allows 8-bit data
transmission.)
Name | Code (decimal) | Description |
EOF | 236 | end-of-file |
SUSP | 237 | suspend current process (job control) |
ABORT | 238 | abort process |
EOR | 239 | end of record |
SE | 240 | suboption end |
NOP | 241 | no operation |
DM | 242 | data mark |
BRK | 243 | break |
IP | 244 | interrupt process |
AO | 245 | abort output |
AYT | 246 | are you there? |
EC | 247 | escape character |
EL | 248 | erase line |
GA | 249 | go ahead |
SB | 250 | suboption begin |
WILL | 251 | option negotiation |
WONT | 252 | option negotiation |
IX) | 253 | option negotiation |
DONT | 254 | option negotiation |
IAC | 255 | data byte 255 |
Option Negotiation
Although
Telnet starts with both sides assuming an NVT, the first exchange that
normally takes place across a Telnet connection is option negotiation.
The option negotiation is symmetric - either side can send a request to
the other. Either side can send one of four different requests for any
given option.
1. WILL. The sender wants to enable the option itself.
2. DO. The sender wants the receiver to enable the option.
3. WONT. The sender wants to disable the option itself.
4. DONT. The sender wants the receiver to disable the option.
Since
the rules of Telnet allow a side to either accept or reject a request
to enable an option (cases 1 and 2 above), but require a side to always
honor a request to disable an option (cases 3 and 4 above), these four
cases lead to the six scenarios:
Sender | Receiver | Description |
1. WILL | DO | sender wants to enable option receiver says OK |
2. WILL | DONT | sender wants to enable option receiver says NO |
3. DO | WILL | sender wants receiver to enable option receiver says OK |
4. DO | WONT | sender wants receiver to enable option receiver says NO |
5. WONT | DONT | sender wants to disable option receiver must say OK |
6. DONT | WONT | sender wants receiver to disable option receiver must say OK |
Option negotiation requires 3 bytes: the IAC byte, followed by the byte for WILL, DO, WONT, or DONT, followed by an ID byte specifying the option to enable or disable. Currently more than 40 different options can be negotiated. The Assigned Numbers RFC specifies the value for the option byte and the relevant RFC that describes the option. Some option codes:
Option ID (decimal) | Name | RFC |
1 | echo | 857 |
3 | suppress go ahead | 858 |
5 | status | 859 |
6 | timing mark | 860 |
24 | terminal type | 1091 |
31 | window size | 1073 |
32 | terminal speed remote | 1079 |
33 | flow control | 1372 |
34 | linemode | 1184 |
36 | environment variables | 1408 |
Telnet
option negotiation, like most of the Telnet protocol, is intended to be
symmetrical. Either end can initiate the negotiation of an option. But
remote login is not a symmetrical application. The client performs some
tasks, and the server performs others.
Suboption Negotiation
Some
options require more information than just "enable" or "disable."
Specifying the terminal type is an example: an ASCII string must be sent
by the client identifying the type of terminal. To handle these
options, suboption negotiation is defined.
RFC 1091 [VanBokkelen
1989] defines the suboption negotiation for the terminal type. First one
side (normally the client) asks to enable the option by sending the
3-byte sequence
where 24 (decimal) is the option ID for the terminal type option. If the receiver (the server) says OK, its response is
The server then sends
asking the client for its terminal type. SB is the suboption-begin command. The next byte of 24 identifies that this is a suboption for the terminal type option. (SB is always followed by the option number to which the suboption refers.) The next byte of 1 means "send your terminal type." The suboption-end command must be prefixed by an IAC, just like the SB command. The client responds with the command
if
its terminal type is the string ibmpc. The fourth byte, 0, means "my
terminal type is." (The "official" list of acceptable terminal types is
in the Assigned Numbers RFC, but on Unix systems at least, any name that
is acceptable to the server is OK. This is normally the terminals
supported by either the termcap or terminfo database.) The terminal type
is specified in the Telnet suboption as all uppercase, and normally
converted to lowercase by the server.
Half-Duplex, Character at a Time, Line at a Time, or Linemode?
There are four modes of operation for most Telnet clients and servers.
1. Half-duplex.
This
is the default mode, but it is rarely used today. The default NVT is a
half-duplex device that requires a GO AHEAD command (GA) from the server
before accepting user input. The user input is echoed locally from the
NVT keyboard to the NVT printer so that only completed lines are sent
from the client to the server.
While this provides the lowest common
denominator for terminal support, it doesn't adequately handle
full-duplex terminals communicating with hosts that support full-duplex
communications, which is the norm today. RFC 857 [Postel and Reynolds
1983c] defines the ECHO option and RFC 858 [Postel and Reynolds 1983d]
defines the SUPPRESS GO AHEAD option. The combination of these two
options provides support for the next mode, character at a time, with
remote echo.
2. Character at a time.
This is what we saw with
Rlogin. Each character we type is sent by itself to the server. The
server echoes most characters, unless the application on the server
turns echoing off.
The problems with this mode are perceptible delays
in echoing across long delay networks and the high volume of network
traffic. Nevertheless, we'll see this is the common default for most
implementations today.
We'll see that the way to enter this mode is
for the server to have the SUPPRESS GO AHEAD option enabled. This can be
negotiated by having the client send a DO SUPPRESS GO AHEAD (asking to
enable the option at the server), or the server sending a WILL SUPPRESS
GO AHEAD to the client (asking to enable the option itself). The server
normally follows this with a WILL ECHO, asking to do the echoing.
3. Line at a time.
This
is often called "kludge line mode," because its implementation comes
from reading between the lines in RFC 858. This REG states that both the
ECHO and SUPPRESS GO AHEAD options must be in effect to have
character-at-a-time input with remote echo. Kludge line mode takes this
to mean that when either of these options is not enabled, Telnet is in a
line-at-a-time mode.
4. Linemode.
We use this term to refer
to the real linemode option, defined in RFC 1184 [Bor-man 1990]. This
option is negotiated between the client and server and corrects all the
deficiencies in the kludge line mode. Newer implementations support this
option.
Synch Signal
Telnet
defines its synch signal as the Data Mark command sent as TCP urgent
data. The DM command is the synchronization mark in the data stream that
tells the receiver to return to normal processing. It can be sent in
either direction across a Telnet connection.