mirror of https://github.com/tLDP/LDP
1218 lines
54 KiB
Plaintext
1218 lines
54 KiB
Plaintext
<chapter id="X-087-2-appl"><title>Important<?lb>Network Features</title>
|
|
|
|
<para>
|
|
After successfully setting up IP and the resolver, you then must look at
|
|
the services you want to provide over the network. This chapter covers the
|
|
configuration of a few simple network applications, including the
|
|
<command>inetd</command> server and the programs from the
|
|
<command>rlogin</command> family. We'll also deal briefly with the Remote
|
|
Procedure Call interface, upon which services like the Network File System (NFS)
|
|
and the Network Information System (NIS) are based. The configuration of
|
|
NFS and NIS, however, is more complex and are described in separate
|
|
chapters, as are electronic mail and network news.
|
|
</para>
|
|
|
|
<para>
|
|
Of course, we can't cover all network applications in this book. If you
|
|
want to install one that's not discussed here, like <command>talk</command>,
|
|
<command>gopher</command>, or <command>http</command>, please refer to
|
|
the manual pages of the server for details.
|
|
</para>
|
|
|
|
<sect1 id="X-087-2-appl.inetd"><title>The inetd Super Server</title>
|
|
<indexterm id="chfe.inetd.svr" class="startofrange"><primary>inetd super server</primary></indexterm>
|
|
<indexterm><primary>services</primary><secondary>setting up</secondary></indexterm>
|
|
<indexterm id="idx-servercommandinetd" class="startofrange"><primary>servers</primary><secondary>inetd</secondary></indexterm>
|
|
<indexterm><primary>configuring</primary><secondary>networks</secondary><tertiary>services</tertiary></indexterm>
|
|
<indexterm><primary>daemons</primary></indexterm>
|
|
<indexterm><primary>Internet</primary><secondary>daemon</secondary></indexterm>
|
|
<para>
|
|
Programs that provide application services via the network are called
|
|
network <emphasis>daemons</emphasis>. A daemon is a program that opens a
|
|
port, most commonly a well-known service port, and waits for incoming
|
|
connections on it. If one occurs, the daemon creates a child process that
|
|
accepts the connection, while the parent continues to listen for further
|
|
requests. This mechanism works well, but has a few disadvantages; at
|
|
least one instance of every possible service you wish to provide must be
|
|
active in memory at all times. In addition, the software routines that
|
|
do the listening and port handling must be replicated in every network daemon.
|
|
</para>
|
|
|
|
<para>
|
|
To overcome these inefficiencies, most Unix installations run a special
|
|
network daemon, what you might consider a “super server.” This
|
|
daemon creates sockets on behalf of a number of services and listens on
|
|
all of them simultaneously. When an incoming connection is received on
|
|
any of these sockets, the super server accepts the connection and spawns
|
|
the server specified for this port, passing the socket across to the child
|
|
to manage. The server then returns to listening.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm id="idx-filenameinetdconf" class="startofrange"><primary>inetd.conf file</primary></indexterm>
|
|
<indexterm><primary>chargen (internal service)</primary></indexterm>
|
|
<indexterm><primary>daytime (internal service)</primary></indexterm>
|
|
The most common super server is called <command>inetd</command>,
|
|
the Internet Daemon. It is started at system boot time and takes the list
|
|
of services it is to manage from a startup file named
|
|
<filename>/etc/inetd.conf</filename>. In addition to those servers,
|
|
there are a number of trivial services performed by <command>inetd</command>
|
|
itself called <emphasis>internal services</emphasis>. They include
|
|
<command>chargen</command>, which simply generates a string of characters,
|
|
and <command>daytime</command>, which returns the system's idea of the time
|
|
of day.
|
|
</para>
|
|
|
|
<para>
|
|
An entry in this file consists of a single line made up of the
|
|
following fields:
|
|
|
|
<screen>
|
|
<replaceable>service</replaceable> <replaceable>type</replaceable> <replaceable>protocol</replaceable> <replaceable>wait</replaceable> <replaceable>user</replaceable> <replaceable>server</replaceable> <replaceable>cmdline</replaceable>
|
|
</screen>
|
|
</para>
|
|
|
|
<para>
|
|
Each of the fields is described in the following list:
|
|
</para>
|
|
|
|
<variablelist>
|
|
<varlistentry><term><replaceable>service</replaceable></term>
|
|
<listitem><para>
|
|
Gives the service name. The service name has to be translated to a port
|
|
number by looking it up in the <filename>/etc/services</filename> file. This
|
|
file will be described later in this chapter in the section <xref linkend="X-087-2-appl.services">.”
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term><replaceable>type</replaceable></term>
|
|
<listitem><para>
|
|
Specifies a socket type, either <systemitem role="keyword">stream</systemitem>
|
|
(for connection-oriented protocols) or
|
|
<systemitem role="keyword">dgram</systemitem> (for datagram protocols).
|
|
TCP-based services should therefore always use
|
|
<systemitem role="keyword">stream</systemitem>, while UDP-based services
|
|
should always use <systemitem role="keyword">dgram</systemitem>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term><replaceable>protocol</replaceable></term>
|
|
<listitem><para>
|
|
Names the transport protocol used by the service. This must be a valid
|
|
protocol name found in the <filename>protocols</filename> file, explained
|
|
later.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term><replaceable>wait</replaceable></term>
|
|
<listitem><para>
|
|
This option applies only to <systemitem role="keyword">dgram</systemitem>
|
|
sockets. It can be either <systemitem role="keyword">wait</systemitem> or
|
|
<systemitem role="keyword">nowait</systemitem>. If
|
|
<systemitem role="keyword">wait</systemitem> is specified,
|
|
<command>inetd</command> executes only one server for the specified
|
|
port at any time. Otherwise, it immediately continues to listen on
|
|
the port after executing the server.
|
|
</para>
|
|
|
|
<para>
|
|
This is useful for “single-threaded” servers that read all
|
|
incoming datagrams until no more arrive, and then exit. Most RPC servers
|
|
are of this type and should therefore specify
|
|
<systemitem role="keyword">wait</systemitem>. The opposite type,
|
|
“multi-threaded” servers, allow an unlimited number of
|
|
instances to run concurrently. These servers should specify
|
|
<systemitem role="keyword">nowait</systemitem>.
|
|
</para>
|
|
|
|
<para>
|
|
<systemitem role="keyword">stream</systemitem> sockets should always use
|
|
<systemitem role="keyword">nowait</systemitem>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term><replaceable>user</replaceable></term>
|
|
<listitem><para>
|
|
This is the login ID of the user who will own the process when it is
|
|
executing. This will frequently be the <systemitem role="userid">root</systemitem>
|
|
user, but some services may use different accounts. It is a very good idea to
|
|
apply the principle of least privilege here, which states that you shouldn't
|
|
run a command under a privileged account if the program doesn't require this for
|
|
proper functioning. For example, the NNTP news server runs as
|
|
<systemitem role="userid">news</systemitem>, while services that may pose
|
|
a security risk (such as <command>tftp</command> or <command>finger</command>)
|
|
are often run as <systemitem role="userid">nobody</systemitem>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term><replaceable>server</replaceable></term>
|
|
<listitem><para>
|
|
Gives the full pathname of the server program to be executed. Internal
|
|
services are marked by the keyword
|
|
<systemitem role="keyword">internal</systemitem>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term><replaceable>cmdline</replaceable></term>
|
|
<listitem><para>
|
|
This is the command line to be passed to the server. It starts with the
|
|
name of the server to be executed and can include any arguments that need
|
|
to be passed to it. If you are using the TCP wrapper, you specify
|
|
the full pathname to the server here. If not, then you just specify the
|
|
server name as you'd like it to appear in a process list. We'll talk about
|
|
the TCP wrapper shortly.
|
|
</para>
|
|
|
|
<para>
|
|
This field is empty for internal services.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
<para>
|
|
<indexterm><primary>security</primary><secondary>TCP servers</secondary></indexterm>
|
|
<indexterm><primary>finger daemon</primary></indexterm>
|
|
A sample <filename>inetd.conf</filename> file is shown in
|
|
<xref linkend="X-087-2-appl.fig.inetd.conf">. The <command>finger</command>
|
|
service is commented out so that it is not available. This is often done
|
|
for security reasons, because it can be used by attackers to obtain names
|
|
and other details of users on your system.
|
|
</para>
|
|
|
|
<example id="X-087-2-appl.fig.inetd.conf">
|
|
<title>A Sample /etc/inetd.conf File</title>
|
|
<screen>
|
|
#
|
|
# inetd services
|
|
ftp stream tcp nowait root /usr/sbin/ftpd in.ftpd -l
|
|
telnet stream tcp nowait root /usr/sbin/telnetd in.telnetd -b/etc/issue
|
|
#finger stream tcp nowait bin /usr/sbin/fingerd in.fingerd
|
|
#tftp dgram udp wait nobody /usr/sbin/tftpd in.tftpd
|
|
#tftp dgram udp wait nobody /usr/sbin/tftpd in.tftpd /boot/diskless
|
|
#login stream tcp nowait root /usr/sbin/rlogind in.rlogind
|
|
#shell stream tcp nowait root /usr/sbin/rshd in.rshd
|
|
#exec stream tcp nowait root /usr/sbin/rexecd in.rexecd
|
|
#
|
|
# inetd internal services
|
|
#
|
|
daytime stream tcp nowait root internal
|
|
daytime dgram udp nowait root internal
|
|
time stream tcp nowait root internal
|
|
time dgram udp nowait root internal
|
|
echo stream tcp nowait root internal
|
|
echo dgram udp nowait root internal
|
|
discard stream tcp nowait root internal
|
|
discard dgram udp nowait root internal
|
|
chargen stream tcp nowait root internal
|
|
chargen dgram udp nowait root internal
|
|
</screen>
|
|
</example>
|
|
|
|
<para>
|
|
<indexterm><primary>TFTP (Trivial File Transfer Protocol)</primary></indexterm>
|
|
<indexterm><primary sortas="etc/passwd file">/etc/passwd file</primary></indexterm>
|
|
The <command>tftp</command> daemon is shown commented out as well.
|
|
<command>tftp</command> implements the <emphasis>Trivial File Transfer
|
|
Protocol</emphasis> (TFTP), which allows someone to transfer any
|
|
world-readable files from your system without password checking.
|
|
This is especially harmful with the <filename>/etc/passwd</filename> file, and even more so when you don't use shadow passwords.
|
|
</para>
|
|
|
|
<para>
|
|
TFTP is commonly used by diskless clients and Xterminals to download their
|
|
code from a boot server. If you need to run <command>tftpd</command> for this
|
|
reason, make sure to limit its scope to those directories from which clients
|
|
will retrieve files; you will need to add those directory names to
|
|
<command>tftpd</command>'s command line. This is shown in the second
|
|
<command>tftp</command> line in the example.
|
|
<indexterm class="endofrange" startref="idx-servercommandinetd">
|
|
<indexterm class="endofrange" startref="chfe.inetd.svr">
|
|
<indexterm class="endofrange" startref="idx-filenameinetdconf">
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 id="X-087-2-appl.tcpd"><title>The tcpd Access Control Facility</title>
|
|
<indexterm><primary>security</primary><secondary>TCP servers</secondary></indexterm>
|
|
<indexterm><primary>services</primary><secondary>restricting access to</secondary></indexterm>
|
|
<indexterm><primary>access</primary><secondary>restricting</secondary></indexterm>
|
|
<indexterm><primary>restricting access to services</primary></indexterm>
|
|
<indexterm><primary>wrapper, TCP</primary></indexterm>
|
|
<indexterm><primary>TCP (Transmission Control Protocol)</primary><secondary>wrapper program</secondary></indexterm>
|
|
<indexterm id="idx-commandtcpdcommand-1" class="startofrange"><primary>tcpd daemon wrapper</primary></indexterm>
|
|
<indexterm id="idx-servercommandtcpdcommand-1" class="startofrange"><primary>servers</primary><secondary>tcpd daemon wrapper</secondary></indexterm>
|
|
<indexterm><primary>daemons</primary><secondary>wrapping via tcpd</secondary></indexterm>
|
|
<para>
|
|
Since opening a computer to network access involves many security risks,
|
|
applications are designed to guard against several types of attacks. Some
|
|
security features, however, may be flawed (most drastically demonstrated by the
|
|
RTM Internet worm, which exploited a hole in a number of programs, including old
|
|
versions of the sendmail mail daemon), or do not distinguish between secure
|
|
hosts from which requests for a particular service will be accepted and
|
|
insecure hosts whose requests should be rejected. We've already briefly
|
|
discussed the <command>finger</command> and <command>tftp</command> services.
|
|
Network Administrator would want to limit access to these services to
|
|
“trusted hosts” only, which is impossible with the usual setup,
|
|
for which <command>inetd</command> provides this service either to all clients
|
|
or not at all.
|
|
</para>
|
|
|
|
<para>
|
|
A useful tool for managing host-specific access is <command>tcpd</command>,
|
|
often called the daemon
|
|
“wrapper.”<footnote id="X-087-2-FNFE01"><para>
|
|
Written by Wietse Venema,
|
|
<systemitem role="emailaddr">wietse@wzv.win.tue.nl</systemitem>.
|
|
</para>
|
|
</footnote>
|
|
For TCP services you want to monitor or protect, it is invoked instead of the
|
|
server program. <command>tcpd</command> checks if the remote host is allowed
|
|
to use that service, and only if this succeeds will it execute the real server
|
|
program. <command>tcpd</command> also logs the request to the
|
|
<command>syslog</command> daemon. Note that this does not work with
|
|
UDP-based services.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm><primary>finger daemon</primary><secondary>wrapping via tcpd</secondary></indexterm>
|
|
For example, to wrap the <command>finger</command> daemon, you have to change
|
|
the corresponding line in <filename>inetd.conf</filename> from this:
|
|
|
|
<screen>
|
|
# unwrapped finger daemon
|
|
finger stream tcp nowait bin /usr/sbin/fingerd in.fingerd
|
|
</screen>
|
|
|
|
to this:
|
|
|
|
<screen>
|
|
# wrap finger daemon
|
|
finger stream tcp nowait root /usr/sbin/tcpd in.fingerd
|
|
</screen>
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm><primary>syslog</primary></indexterm>
|
|
Without adding any access control, this will appear to the client as
|
|
the usual <command>finger</command> setup, except that any requests are logged
|
|
to <command>syslog</command>'s <emphasis>auth</emphasis>
|
|
facility.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm><primary sortas="etc/hosts.allow file">/etc/hosts.allow file</primary></indexterm>
|
|
<indexterm><primary sortas="etc/hosts.deny file">/etc/hosts.deny file</primary></indexterm>
|
|
Two files called <filename>/etc/hosts.allow</filename> and
|
|
<filename>/etc/hosts.deny</filename> implement access control.
|
|
They contain entries that allow and deny access to certain services and hosts.
|
|
When <command>tcpd</command> handles a request for a service such as
|
|
<command>finger</command> from a client host named
|
|
<systemitem role="sitename">biff.foobar.com</systemitem>, it scans
|
|
<filename>hosts.allow</filename> and <filename>hosts.deny</filename>
|
|
(in this order) for an entry matching both the service and client host.
|
|
If a matching entry is found in <filename>hosts.allow</filename>, access
|
|
is granted and <command>tcpd</command> doesn't consult the
|
|
<filename>hosts.deny</filename> file. If no match is found in the
|
|
<filename>hosts.allow</filename> file, but a match is found in
|
|
<filename>hosts.deny</filename>, the request is rejected by closing down the
|
|
connection. The request is accepted if no match is found at all.
|
|
</para>
|
|
|
|
<para>
|
|
Entries in the access files look like this:
|
|
|
|
<screen>
|
|
<replaceable>servicelist</replaceable>: <replaceable>hostlist</replaceable> [:<replaceable>shellcmd</replaceable>]
|
|
</screen>
|
|
</para>
|
|
|
|
<para>
|
|
<replaceable>servicelist</replaceable> is a list of service names from
|
|
<filename>/etc/services</filename>, or the keyword
|
|
<systemitem role="keyword">ALL</systemitem>. To match all services except
|
|
<command>finger</command> and <command>tftp</command>, use
|
|
<systemitem role="keyword">ALL</systemitem>
|
|
<systemitem role="keyword">EXCEPT</systemitem>
|
|
<literal>finger, tftp</literal>.
|
|
</para>
|
|
|
|
<para>
|
|
<replaceable>hostlist</replaceable> is a list of hostnames, IP addresses,
|
|
or the keywords <systemitem role="keyword">ALL</systemitem>,
|
|
<systemitem role="keyword">LOCAL</systemitem>,
|
|
<systemitem role="keyword">UNKNOWN</systemitem> or
|
|
<systemitem role="keyword">PARANOID</systemitem>.
|
|
<systemitem role="keyword">ALL</systemitem> matches any host, while
|
|
<systemitem role="keyword">LOCAL</systemitem> matches hostnames that don't
|
|
contain a dot.<footnote id="X-087-2-FNFE02"><para>
|
|
Usually only local hostnames obtained from lookups in
|
|
<filename>/etc/hosts</filename> contain no dots.
|
|
</para>
|
|
</footnote>
|
|
|
|
<systemitem role="keyword">UNKNOWN</systemitem> matches any hosts whose name
|
|
or address lookup failed. <systemitem role="keyword">PARANOID</systemitem>
|
|
matches any host whose hostname does not resolve back to its IP
|
|
address.<footnote id="X-087-2-FNFE03"><para>
|
|
While its name suggests it is an extreme measure, the <systemitem role="keyword">PARANOID</systemitem> keyword is
|
|
a good default, as it protects you against mailicious hosts pretending to
|
|
be someone they are not. Not all <command>tcpd</command> are supplied with
|
|
<systemitem role="keyword">PARANOID</systemitem> compiled in; if yours is not, you need to recompile
|
|
<command>tcpd</command> to use it.
|
|
</para>
|
|
</footnote>
|
|
|
|
A name starting with a dot matches all hosts whose domain is equal to this
|
|
name. For example, <systemitem role="sitename">.foobar.com</systemitem> matches
|
|
<systemitem role="sitename">biff.foobar.com</systemitem>, but not
|
|
<systemitem role="sitename">nurks.fredsville.com</systemitem>. A pattern that
|
|
ends with a dot matches any host whose IP address begins with the supplied
|
|
pattern, so <systemitem role="sitename">172.16.</systemitem> matches
|
|
<systemitem role="sitename">172.16.32.0</systemitem>, but not
|
|
<systemitem role="sitename">172.15.9.1</systemitem>. A pattern of the form
|
|
<literal><replaceable>n.n.n.n</replaceable>/<replaceable>m.m.m.m</replaceable>
|
|
</literal><emphasis></emphasis> is treated as an IP address and network mask, so we could specify
|
|
our previous example as
|
|
<systemitem role="sitename">172.16.0.0/255.255.0.0</systemitem> instead.
|
|
Lastly, any pattern beginning with a “/” character allows you to
|
|
specify a file that is presumed to contain a list of hostname or IP address
|
|
patterns, any of which are allowed to match. So a pattern that looked like
|
|
<emphasis>/var/access/trustedhosts</emphasis> would cause
|
|
the <command>tcpd</command> daemon to read that file, testing if any of the
|
|
lines in it matched the connecting host.
|
|
</para>
|
|
|
|
<para>
|
|
To deny access to the <command>finger</command> and <command>tftp</command>
|
|
services to all but the local hosts, put the following in
|
|
<filename>/etc/hosts.deny</filename> and leave
|
|
<filename>/etc/hosts.allow</filename> empty:
|
|
|
|
<screen>
|
|
in.tftpd, in.fingerd: ALL EXCEPT LOCAL, <replaceable>.your.domain</replaceable>
|
|
</screen>
|
|
</para>
|
|
|
|
<para>
|
|
The optional <replaceable>shellcmd</replaceable> field may contain a shell
|
|
command to be invoked when the entry is matched. This is useful to set up
|
|
traps that may expose potential attackers. The following example creates
|
|
a log file listing the user and host connecting, and if the host is not
|
|
<emphasis role=bold>vlager.vbrew.com</emphasis> it will append the
|
|
output of a <command>finger</command> to that host:
|
|
|
|
<screen>
|
|
in.ftpd: ALL EXCEPT LOCAL, .vbrew.com : \
|
|
echo "request from %d@%h: >> /var/log/finger.log; \
|
|
if [ %h != "vlager.vbrew.com:" ]; then \
|
|
finger -l @%h >> /var/log/finger.log \
|
|
fi
|
|
</screen>
|
|
</para>
|
|
|
|
<para>
|
|
The <systemitem role="keyword">%h</systemitem> and
|
|
<systemitem role="keyword">%d</systemitem> arguments are expanded by
|
|
<command>tcpd</command> to the client hostname and service name,
|
|
respectively. Please refer to the <filename>hosts_access(5)</filename>
|
|
manual page for details.
|
|
|
|
<indexterm class="endofrange" startref="idx-commandtcpdcommand-1">
|
|
<indexterm class="endofrange" startref="idx-servercommandtcpdcommand-1">
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 id="X-087-2-appl.services"><title>The Services and Protocols Files</title>
|
|
<indexterm id="idx-filenameservicesfilename-1" class="startofrange"><primary>services file</primary></indexterm>
|
|
<indexterm id="idx-filenameprotocolsfilename-1" class="startofrange"><primary>protocols file</primary></indexterm>
|
|
<indexterm><primary>services</primary><secondary>well-known</secondary></indexterm>
|
|
<indexterm><primary sortas="etc/services file">/etc/services file</primary></indexterm>
|
|
|
|
<para>
|
|
The port numbers on which certain “standard” services are
|
|
offered are defined in the Assigned Numbers RFC. To enable server and client
|
|
programs to convert service names to these numbers, at least part of
|
|
the list is kept on each host; it is stored in a file called
|
|
<filename>/etc/services</filename>. An entry is made up like this:
|
|
|
|
<screen>
|
|
<replaceable>service</replaceable> <replaceable>port</replaceable>/<replaceable>protocol</replaceable> [<replaceable>aliases</replaceable>]
|
|
</screen>
|
|
</para>
|
|
|
|
<para>
|
|
Here, <replaceable>service</replaceable> specifies the service name,
|
|
<replaceable>port</replaceable> defines the port the service is offered on,
|
|
and <replaceable>protocol</replaceable> defines which transport protocol
|
|
is used. Commonly, the latter field is either
|
|
<replaceable>udp</replaceable> or
|
|
<replaceable>tcp</replaceable>. It is possible for a service to be
|
|
offered for more than one protocol, as well as offering different services on
|
|
the same port as long as the protocols are different. The
|
|
<replaceable>aliases</replaceable> field allows you to specify alternative
|
|
names for the same service.
|
|
</para>
|
|
|
|
<para>
|
|
Usually, you don't have to change the services file that comes along
|
|
with the network software on your Linux system. Nevertheless, we give a
|
|
small excerpt from that file in <xref linkend="X-087-2-etc.services">.
|
|
</para>
|
|
|
|
<example id="X-087-2-etc.services">
|
|
<title>A Sample /etc/services File</title>
|
|
<screen>
|
|
# The services file:
|
|
#
|
|
# well-known services
|
|
echo 7/tcp # Echo
|
|
echo 7/udp #
|
|
discard 9/tcp sink null # Discard
|
|
discard 9/udp sink null #
|
|
daytime 13/tcp # Daytime
|
|
daytime 13/udp #
|
|
chargen 19/tcp ttytst source # Character Generator
|
|
chargen 19/udp ttytst source #
|
|
ftp-data 20/tcp # File Transfer Protocol (Data)
|
|
ftp 21/tcp # File Transfer Protocol (Control)
|
|
telnet 23/tcp # Virtual Terminal Protocol
|
|
smtp 25/tcp # Simple Mail Transfer Protocol
|
|
nntp 119/tcp readnews # Network News Transfer Protocol
|
|
#
|
|
# UNIX services
|
|
exec 512/tcp # BSD rexecd
|
|
biff 512/udp comsat # mail notification
|
|
login 513/tcp # remote login
|
|
who 513/udp whod # remote who and uptime
|
|
shell 514/tcp cmd # remote command, no passwd used
|
|
syslog 514/udp # remote system logging
|
|
printer 515/tcp spooler # remote print spooling
|
|
route 520/udp router routed # routing information protocol
|
|
</screen>
|
|
</example>
|
|
|
|
<para>
|
|
<indexterm><primary>echo service</primary></indexterm>
|
|
Note that the <command>echo</command> service is offered on port 7 for both
|
|
TCP and UDP, and that port 512 is used for two
|
|
different services: remote execution (<command>rexec</command>) using TCP,
|
|
and the <command>COMSAT</command> daemon, which notifies users of new mail, over UDP
|
|
(see <command>xbiff(1x)</command> ).
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm><primary sortas="etc/protocols file">/etc/protocols file</primary></indexterm>
|
|
<indexterm><primary>protocol numbers</primary></indexterm>
|
|
Like the services file, the networking library needs a way to translate
|
|
protocol names—for example, those used in the services file—to
|
|
protocol numbers understood by the IP layer on other hosts. This is done by
|
|
looking up the name in the <filename>/etc/protocols</filename> file. It
|
|
contains one entry per line, each containing a protocol name, and the
|
|
associated number. Having to touch this file is even more unlikely than
|
|
having to meddle with <filename>/etc/services</filename>. A sample file
|
|
is given in <xref linkend="X-087-2-etc.protocols">.
|
|
</para>
|
|
|
|
<example id="X-087-2-etc.protocols">
|
|
<title>A Sample /etc/protocols File</title>
|
|
<screen>
|
|
#
|
|
# Internet (IP) protocols
|
|
#
|
|
ip 0 IP # internet protocol, pseudo protocol number
|
|
icmp 1 ICMP # internet control message protocol
|
|
igmp 2 IGMP # internet group multicast protocol
|
|
tcp 6 TCP # transmission control protocol
|
|
udp 17 UDP # user datagram protocol
|
|
raw 255 RAW # RAW IP interface
|
|
</screen>
|
|
</example>
|
|
<indexterm class="endofrange" startref="idx-filenameservicesfilename-1">
|
|
<indexterm class="endofrange" startref="idx-filenameprotocolsfilename-1">
|
|
</sect1>
|
|
|
|
<sect1 id="X-087-2-appl.rpc"><title>Remote Procedure Call</title>
|
|
<indexterm><primary>RPC (Remote Procedure Call)</primary></indexterm>
|
|
<para>
|
|
The general mechanism for client-server applications is provided by the
|
|
<emphasis>Remote Procedure Call</emphasis> (RPC) package. RPC was developed by Sun
|
|
Microsystems and is a collection of tools and library functions. Important
|
|
applications built on top of RPC are NIS, the Network Information System
|
|
(described in <xref linkend="X-087-2-nis">), and NFS, the Network File System
|
|
(described in <xref linkend="X-087-2-nfs">), which are both described in
|
|
this book.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm><primary>XDR (External Data Representation)</primary></indexterm>
|
|
<INDEXTERM><PRIMARY>External Data Representation (XDR)</PRIMARY></INDEXTERM>
|
|
An RPC server consists of a collection of procedures that a client can call
|
|
by sending an RPC request to the server along with the procedure parameters.
|
|
The server will invoke the indicated procedure on behalf of the client,
|
|
handing back the return value, if there is any. In order to be
|
|
machine-independent, all data exchanged between client and server is
|
|
converted to the <emphasis>External Data Representation</emphasis> format
|
|
(XDR) by the sender, and converted back to the machine-local representation
|
|
by the receiver. RPC relies on standard UDP and TCP sockets to transport the
|
|
XDR formatted data to the remote host. Sun has graciously placed RPC in the
|
|
public domain; it is described in a series of RFCs.
|
|
</para>
|
|
|
|
<para>
|
|
Sometimes improvements to an RPC application introduce incompatible changes
|
|
in the procedure call interface. Of course, simply changing the server would
|
|
crash all applications that still expect the original behavior. Therefore,
|
|
RPC programs have version numbers assigned to them, usually starting with 1,
|
|
and with each new version of the RPC interface, this counter will be bumped up.
|
|
Often, a server may offer several versions simultaneously; clients then
|
|
indicate by the version number in their requests which implementation of
|
|
the service they want to use.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm><primary>rpc file</primary></indexterm>
|
|
<indexterm><primary>RPC (Remote Procedure Call)</primary><secondary>program numbers</secondary></indexterm>
|
|
The communication between RPC servers and clients is somewhat peculiar. An
|
|
RPC server offers one or more collections of procedures; each set is called
|
|
a <emphasis>program</emphasis> and is uniquely identified by a
|
|
<emphasis>program number</emphasis>. A list that maps service names to program
|
|
numbers is usually kept in <filename>/etc/rpc</filename>, an excerpt of which
|
|
is shown in <xref linkend="X-087-2-rpc.fig">.
|
|
</para>
|
|
|
|
<example id="X-087-2-rpc.fig">
|
|
<title>A Sample /etc/rpc File</title>
|
|
<screen>
|
|
#
|
|
# /etc/rpc - miscellaneous RPC-based services
|
|
#
|
|
portmapper 100000 portmap sunrpc
|
|
rstatd 100001 rstat rstat_svc rup perfmeter
|
|
rusersd 100002 rusers
|
|
nfs 100003 nfsprog
|
|
ypserv 100004 ypprog
|
|
mountd 100005 mount showmount
|
|
ypbind 100007
|
|
walld 100008 rwall shutdown
|
|
yppasswdd 100009 yppasswd
|
|
bootparam 100026
|
|
ypupdated 100028 ypupdate
|
|
</screen>
|
|
</example>
|
|
|
|
<para>
|
|
In TCP/IP networks, the authors of RPC faced the problem of mapping
|
|
program numbers to generic network services. They designed each server to
|
|
provide both a TCP and a UDP port for each program and each version. Generally,
|
|
RPC applications use UDP when sending data, and fall back to TCP only
|
|
when the data to be transferred doesn't fit into a single UDP datagram.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm><primary>portmapper daemon</primary></indexterm>
|
|
<indexterm><primary>RPC (Remote Procedure Call)</primary><secondary>mapping ports to programs</secondary></indexterm>
|
|
Of course, client programs need to find out to which port
|
|
a program number maps. Using a configuration file for this would be
|
|
too unflexible; since RPC applications don't use reserved ports, there's
|
|
no guarantee that a port originally meant to be used by our database
|
|
application hasn't been taken by some other process. Therefore, RPC
|
|
applications pick any port they can get and register it with a special program
|
|
called the <emphasis>portmapper daemon</emphasis>. The portmapper acts as a
|
|
service broker for all RPC servers running on its machine. A client that
|
|
wishes to contact a service with a given program number first queries
|
|
the portmapper on the server's host, which returns the TCP and UDP port
|
|
numbers the service can be reached at.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm><primary>inetd super server</primary></indexterm>
|
|
This method introduces a single point of failure, much like the
|
|
<command>inetd</command> daemon does for the standard
|
|
Berkeley services. However, this case is even a little worse because
|
|
when the portmapper dies, all RPC port information is lost; this
|
|
usually means you have to restart all RPC servers manually or reboot
|
|
the entire machine.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm><primary>rpc.portmap daemon</primary></indexterm>
|
|
<indexterm><primary>portmap daemon</primary></indexterm>
|
|
On Linux, the portmapper is called <filename>/sbin/portmap</filename>, or
|
|
sometimes <filename>/usr/sbin/rpc.portmap</filename>. Other than making sure
|
|
it is started from your network boot scripts, the portmapper doesn't require
|
|
any configuration.
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 id="X-087-2-appl.remote"><title>Configuring Remote Login<?lb>and Execution</title>
|
|
<indexterm id="idx-configuringrcommands" class="startofrange"><primary>configuring</primary><secondary>remote login and execution</secondary></indexterm>
|
|
<indexterm><primary>authentication</primary><secondary>on remote hosts</secondary></indexterm>
|
|
<indexterm><primary>remote</primary><secondary>command execution</secondary></indexterm>
|
|
<indexterm><primary>security</primary><secondary>remote login</secondary></indexterm>
|
|
<indexterm><primary>remote</primary><secondary>login</secondary></indexterm>
|
|
<indexterm><primary>remote</primary><secondary>file access</secondary></indexterm>
|
|
<para>
|
|
It's often very useful to execute a command on a remote host and
|
|
have input or output from that command be read from, or written to, a network
|
|
connection.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm><primary>rlogin command</primary></indexterm>
|
|
<indexterm><primary>rcp command</primary></indexterm>
|
|
<indexterm><primary>rsh command</primary></indexterm>
|
|
<indexterm><primary>slogin command</primary></indexterm>
|
|
<indexterm><primary>scp command</primary></indexterm>
|
|
<indexterm><primary>ssh command</primary></indexterm>
|
|
The traditional commands used for executing commands on remote hosts are
|
|
<command>rlogin</command>, <command>rsh</command> and <command>rcp</command>.
|
|
We saw an example of the <command>rlogin</command> command in <xref linkend="X-087-2-intro"> in the section <xref linkend="X-087-2-intro.tcpip.intro">.” We briefly discussed the security
|
|
issues associated with it in <xref linkend="X-087-2-intro.security">” and
|
|
suggested <command>ssh</command> as a replacement.
|
|
The <command>ssh</command> package provides replacements called
|
|
<command>slogin</command>, <command>ssh</command>, and <command>scp</command>.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm><primary>passwords</primary><secondary>remote login and</secondary></indexterm>
|
|
Each of these commands spawns a shell on the remote host and allows the user
|
|
to execute commands. Of course, the client needs to have an account on the
|
|
remote host where the command is to be executed. Thus, all these commands
|
|
use an authentication process. The <emphasis>r</emphasis> commands use a simple
|
|
username and password exchange between the hosts with no encryption, so anyone
|
|
listening could easily intercept the passwords. The <command>ssh</command>
|
|
command suite provides a higher level of security: it uses a technique
|
|
called <command>Public Key Cryptography</command>, which provides
|
|
authentication and encryption between the hosts to ensure that
|
|
neither passwords nor session data are easily intercepted by other hosts.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm><primary>Local Area Networks (LANs)</primary><secondary>remote login</secondary></indexterm>
|
|
It is possible to relax authentication checks for certain users even further. For
|
|
instance, if you frequently have to log into other machines on your LAN,
|
|
you might want to be admitted without having to type your password every
|
|
time. This was always possible with the <emphasis>r</emphasis> commands, but the
|
|
<command>ssh</command> suite allows you to do this a little more easily. It's
|
|
still not a great idea because it means that if an account on one machine
|
|
is breached, access can be gained to all other accounts that user has
|
|
configured for password-less login, but it is very convenient and people will
|
|
use it.
|
|
</para>
|
|
|
|
<para>
|
|
Let's talk about removing the <emphasis>r</emphasis> commands and getting
|
|
<command>ssh</command> to work instead.
|
|
</para>
|
|
|
|
<sect2><title>Disabling the r; Commands</title>
|
|
<para>
|
|
Start by removing the <command>r</command> commands if they're
|
|
installed. The easiest way to disable the old <command>r</command>
|
|
commands is to comment out (or remove) their entries in the
|
|
<filename>/etc/inetd.conf</filename> file. The relevant entries will
|
|
look something like this:
|
|
|
|
<screen>
|
|
# Shell, login, exec and talk are BSD protocols.
|
|
shell stream tcp nowait root /usr/sbin/tcpd /usr/sbin/in.rshd
|
|
login stream tcp nowait root /usr/sbin/tcpd /usr/sbin/in.rlogind
|
|
exec stream tcp nowait root /usr/sbin/tcpd /usr/sbin/in.rexecd
|
|
</screen>
|
|
|
|
You can comment them by placing a <literal>#</literal> character at the start
|
|
of each line, or delete the lines completely. Remember, you need to restart the
|
|
<command>inetd</command> daemon for this change to take effect. Ideally, you
|
|
should remove the daemon programs themselves, too.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2><title>Installing and Configuring ssh</title>
|
|
<para>
|
|
<INDEXTERM id="ssh.command.config" class=startofrange><PRIMARY>ssh command</PRIMARY><SECONDARY>configuring</SECONDARY></INDEXTERM>
|
|
<INDEXTERM id="config.ssh.command" class=startofrange><PRIMARY>configuring</PRIMARY><SECONDARY>ssh command</SECONDARY></INDEXTERM>
|
|
OpenSSH is a free version of the ssh suite of programs; the Linux port can
|
|
be found at
|
|
<systemitem role="url">http://violet.ibs.com.au/openssh/</systemitem> and in
|
|
most modern Linux distributions.<footnote id="X-087-2-FNFE04"><para>
|
|
OpenSSH was developed by the OpenBSD project and is a fine example of the
|
|
benefit of free software.
|
|
</para>
|
|
</footnote>
|
|
We won't describe compilation here; good instructions are included in the
|
|
source. If you can install it from a precompiled package, then it's probably
|
|
wise to do so.
|
|
</para>
|
|
|
|
<para>
|
|
There are two parts to an <command>ssh</command> session. There is an
|
|
<command>ssh</command> client that you need to configure and run on the local
|
|
host and an <command>ssh</command> daemon that must be running on the remote
|
|
host.
|
|
</para>
|
|
|
|
<sect3><title>The ssh daemon</title>
|
|
<para>
|
|
<INDEXTERM id="ssh.sshd.daemon" class=startofrange><PRIMARY>ssh command</PRIMARY><SECONDARY>sshd daemon</SECONDARY></INDEXTERM>
|
|
<INDEXTERM id="sshd.daemon" class=startofrange><PRIMARY>sshd daemon</PRIMARY></INDEXTERM>
|
|
The <command>sshd</command> daemon is the program that listens for network
|
|
connections from <command>ssh</command> clients, manages authentication, and
|
|
executes the requested command. It has one main configuration file called
|
|
<filename>/etc/ssh/sshd_config</filename> and a special file containing a
|
|
key used by the authentication and encryption processes to represent the host
|
|
end. Each host and each client has its own key.
|
|
</para>
|
|
|
|
<para>
|
|
<INDEXTERM><PRIMARY>ssh-keygen utility</PRIMARY></INDEXTERM>
|
|
<INDEXTERM><PRIMARY SORTAS="etc/ssh/ssh_host_key file">/etc/ssh/ssh_host_key file</PRIMARY></INDEXTERM>
|
|
<INDEXTERM><PRIMARY>host keys</PRIMARY></INDEXTERM>
|
|
<INDEXTERM><PRIMARY>keys</PRIMARY><SECONDARY>host</SECONDARY></INDEXTERM>
|
|
A utility called <command>ssh-keygen</command> is supplied to generate
|
|
a random key. This is usually used once at installation time to
|
|
generate the host key, which the system administrator usually stores
|
|
in a file called <filename>/etc/ssh/ssh_host_key</filename>. Keys can
|
|
be of any length of 512 bits or greater. By default,
|
|
<command>ssh-keygen</command> generates keys of 1024 bits in length,
|
|
and most people use the default. To generate a random key, you would
|
|
invoke the <command>ssh-keygen</command> command like this:
|
|
|
|
<screen>
|
|
# <userinput>ssh-keygen -f /etc/ssh/ssh_host_key</userinput>
|
|
</screen>
|
|
|
|
</para>
|
|
|
|
<para>
|
|
You will be prompted to enter a passphrase. However, host keys must not use
|
|
a passphrase, so just press the return key to leave it blank. The program
|
|
output will look something like:
|
|
|
|
<screen>
|
|
Generating RSA keys: ......oooooO...............................oooooO
|
|
Key generation complete.
|
|
Enter passphrase (empty for no passphrase):
|
|
Enter same passphrase again:
|
|
Your identification has been saved in /etc/ssh/ssh_host_key
|
|
Your public key has been saved in /etc/ssh/ssh_host_key.pub
|
|
The key fingerprint is:
|
|
1024 3a:14:78:8e:5a:a3:6b:bc:b0:69:10:23:b7:d8:56:82 root@moria
|
|
</screen>
|
|
</para>
|
|
|
|
<para>
|
|
<INDEXTERM><PRIMARY>private keys</PRIMARY></INDEXTERM>
|
|
<INDEXTERM><PRIMARY>public keys</PRIMARY></INDEXTERM>
|
|
<INDEXTERM><PRIMARY>keys</PRIMARY><SECONDARY>private</SECONDARY></INDEXTERM>
|
|
<INDEXTERM><PRIMARY>keys</PRIMARY><SECONDARY>public</SECONDARY></INDEXTERM>
|
|
<INDEXTERM><PRIMARY SORTAS="etc/ssh/ssh_host_key.pub file">/etc/ssh/ssh_host_key.pub file</PRIMARY></INDEXTERM>
|
|
You will find at the end that two files have been created. The first is
|
|
called the private key, which must be kept secret and will be in
|
|
<filename>/etc/ssh/ssh_host_key</filename>. The second is called the public
|
|
key and is one that you can share; it will be in
|
|
<filename>/etc/ssh/ssh_host_key.pub</filename>.
|
|
</para>
|
|
|
|
<para>
|
|
Armed with the keys for <command>ssh</command> communication, you need to
|
|
create a configuration file. The <command>ssh</command> suite is very
|
|
powerful and the configuration file
|
|
may contain many options. We'll present a simple example to get you started;
|
|
you should refer to the <command>ssh</command> documentation to enable other
|
|
features. The following code shows a safe and minimal
|
|
<command>sshd</command> configuration file. The rest of the configuration
|
|
options are detailed in the <command>sshd</command> (8) manpage:
|
|
</para>
|
|
|
|
<screen>
|
|
# /etc/ssh/sshd_config
|
|
#
|
|
|
|
# The IP adddresses to listen for connections on. 0.0.0.0 means all
|
|
# local addresses.
|
|
ListenAddress 0.0.0.0
|
|
|
|
# The TCP port to listen for connections on. The default is 22.
|
|
Port 22
|
|
|
|
# The name of the host key file.
|
|
HostKey /etc/ssh/ssh_host_key
|
|
|
|
# The length of the key in bits.
|
|
ServerKeyBits 1024
|
|
|
|
# Should we allow root logins via ssh?
|
|
PermitRootLogin no
|
|
|
|
# Should the ssh daemon check users' home directory and files permissions?
|
|
# are safe before allowing login?
|
|
StrictModes yes
|
|
|
|
# Should we allow old ~/.rhosts and /etc/hosts.equiv authentication method?
|
|
RhostsAuthentication no
|
|
# Should we allow pure RSA authentication?
|
|
RSAAuthentication yes
|
|
# Should we allow password authentication?
|
|
PasswordAuthentication yes
|
|
|
|
# Should we allow /etc/hosts.equiv combined with RSA host authentication?
|
|
RhostsRSAAuthentication no
|
|
# Should we ignore ~/.rhosts files?
|
|
IgnoreRhosts yes
|
|
<?troff .ne 7>
|
|
# Should we allow logins to accounts with empty passwords?
|
|
PermitEmptyPasswords no
|
|
</screen>
|
|
|
|
<para>
|
|
It's important to make sure the permissions of the configuration files are
|
|
correct to ensure that system security is maintained. Use the following
|
|
commands:
|
|
|
|
<screen>
|
|
# <userinput>chown -R root:root /etc/ssh</userinput>
|
|
# <userinput>chmod 755 /etc/ssh</userinput>
|
|
# <userinput>chmod 600 /etc/ssh/ssh_host_key</userinput>
|
|
# <userinput>chmod 644 /etc/ssh/ssh_host_key.pub</userinput>
|
|
# <userinput>chmod 644 /etc/ssh/sshd_config</userinput>
|
|
</screen>
|
|
</para>
|
|
|
|
<para>
|
|
<?troff .hw simple>
|
|
The final stage of <command>sshd</command> administration daemon is
|
|
to run it. Normally you'd create an <filename>rc</filename> file
|
|
for it or add it to an existing one, so that it is automatically executed
|
|
at boot time. The daemon runs standalone and doesn't require any entry in
|
|
the <filename>/etc/inetd.conf</filename> file. The daemon must be run as the
|
|
<literal>root</literal> user. The syntax is very simple:
|
|
|
|
<screen>
|
|
/usr/sbin/sshd
|
|
</screen>
|
|
|
|
The <command>sshd</command> daemon will automatically place itself into the
|
|
background when being run. You are now ready to accept <emphasis>ssh</emphasis>
|
|
connections.
|
|
</para>
|
|
<INDEXTERM startref="ssh.sshd.daemon" class=endofrange>
|
|
<INDEXTERM startref="sshd.daemon" class=endofrange>
|
|
</sect3>
|
|
|
|
<sect3><title>The ssh client</title>
|
|
<para>
|
|
<INDEXTERM id="ssh.ssh.clients" class=startofrange><PRIMARY>ssh command</PRIMARY><SECONDARY>clients</SECONDARY></INDEXTERM>
|
|
<indexterm><primary>slogin command</primary></indexterm>
|
|
<indexterm><primary>scp command</primary></indexterm>
|
|
<INDEXTERM><PRIMARY SORTAS="etc/ssh/ssh_config file">/etc/ssh/ssh_config file</PRIMARY></INDEXTERM>
|
|
There are a number of <command>ssh</command> client programs:
|
|
<command>slogin</command>, <command>scp</command> and <command>ssh</command>.
|
|
They each read the same configuration file, usually called
|
|
<filename>/etc/ssh/ssh_config</filename>. They each also read configuration
|
|
files from the <filename>.ssh</filename> directory in the home directory
|
|
of the user executing them. The most important of these files is the
|
|
<filename>.ssh/config</filename> file, which may contain options that override
|
|
those specified in the <filename>/etc/ssh/ssh_config</filename> file, the
|
|
<filename>.ssh/identity</filename> file, which contains the user's own
|
|
private key, and the corresponding <filename>.ssh/identity.pub</filename>
|
|
file, containing the user's public key. Other important files are <filename>.ssh/known_hosts</filename> and
|
|
<filename>.ssh/authorized_keys</filename>; we'll talk about those later in <xref linkend="X-087-2-features.ssh.using">.” First, let's create the global
|
|
configuration file and the user key file.
|
|
</para>
|
|
|
|
<para>
|
|
<filename>/etc/ssh/ssh_config</filename> is very similar to the server
|
|
configuration file. Again, there are lots of features you can configure, but
|
|
a minimal configuration looks like that presented in
|
|
<xref linkend="X-087-2-features.ssh.conf">. The rest of the configuration
|
|
options are detailed in the <command>sshd(8)</command> manpage. You can add sections that match
|
|
specific hosts or groups of hosts. The parameter to the
|
|
“<literal>Host</literal>” statement may be either the full name of
|
|
a host or a wildcard specification, as we've used in our example, to match all
|
|
hosts. We could create an entry that used, for example,
|
|
<literal>Host *.vbrew.com</literal> to match any host in the
|
|
<literal>vbrew.com</literal> domain.
|
|
</para>
|
|
|
|
<example id="X-087-2-features.ssh.conf">
|
|
<title>Example ssh Client Configuration File</title>
|
|
<screen>
|
|
# /etc/ssh/ssh_config
|
|
|
|
# Default options to use when connecting to a remote host
|
|
Host *
|
|
# Compress the session data?
|
|
Compression yes
|
|
# .. using which compression level? (1 - fast/poor, 9 - slow/good)
|
|
CompressionLevel 6
|
|
|
|
# Fall back to rsh if the secure connection fails?
|
|
FallBackToRsh no
|
|
|
|
# Should we send keep-alive messages? Useful if you use IP masquerade
|
|
KeepAlive yes
|
|
|
|
# Try RSA authentication?
|
|
RSAAuthentication yes
|
|
# Try RSA authentication in combination with .rhosts authentication?
|
|
RhostsRSAAuthentication yes
|
|
</screen>
|
|
</example>
|
|
|
|
<para>
|
|
<INDEXTERM><PRIMARY>ssh-keygen utility</PRIMARY></INDEXTERM>
|
|
We mentioned in the server configuration section that every host and user has a key. The user's key is stored in his or her
|
|
<filename>~/.ssh/indentity</filename> file. To generate the key, use the
|
|
same <command>ssh-keygen</command> command as we used to generate the
|
|
host key, except this time you do not need to specify the name of the file
|
|
in which you save the key. The <command>ssh-keygen</command> defaults to
|
|
the correct location, but it prompts you to enter a filename in case you'd like
|
|
to save it elsewhere. It is sometimes useful to have multiple identity files,
|
|
so <command>ssh</command> allows this.
|
|
Just as before, <command>ssh-keygen</command> will prompt you to entry a
|
|
passphrase. Passphrases add yet another level of security and are a good idea.
|
|
Your passphrase won't be echoed on the screen when you type it.
|
|
<warning><para>
|
|
There is no way to recover a passphrase if you forget it. Make sure it is
|
|
something you will remember, but as with all passwords, make it something
|
|
that isn't obvious, like a proper noun or your name. For a passphrase to
|
|
be truly effective, it should be between 10 and 30 characters
|
|
long and not be plain English prose. Try to throw in some unusual
|
|
characters. If you forget your passphrase, you will be forced to generate a
|
|
new key.
|
|
</para></warning>
|
|
<INDEXTERM><PRIMARY>private keys</PRIMARY></INDEXTERM>
|
|
<INDEXTERM><PRIMARY>public keys</PRIMARY></INDEXTERM>
|
|
<INDEXTERM><PRIMARY>keys</PRIMARY><SECONDARY>private</SECONDARY></INDEXTERM>
|
|
<INDEXTERM><PRIMARY>keys</PRIMARY><SECONDARY>public</SECONDARY></INDEXTERM>
|
|
You should ask each of your users to run the <command>ssh-keygen</command>
|
|
command just once to ensure their key file is created correctly. The
|
|
<command>ssh-keygen</command> will create their <filename>~/.ssh/</filename>
|
|
directories for them with appropriate permissions and create their private and
|
|
public keys in <filename>.ssh/identity</filename> and
|
|
<filename>.ssh/identity.pub</filename>, respectively. A sample session
|
|
should look like:
|
|
|
|
<screen>
|
|
$ <userinput>ssh-keygen</userinput>
|
|
Generating RSA keys: .......oooooO..............................
|
|
Key generation complete.
|
|
Enter file in which to save the key (/home/maggie/.ssh/identity):
|
|
Enter passphrase (empty for no passphrase):
|
|
Enter same passphrase again:
|
|
Your identification has been saved in /home/maggie/.ssh/identity.
|
|
Your public key has been saved in /home/maggie/.ssh/identity.pub.
|
|
The key fingerprint is:
|
|
1024 85:49:53:f4:8a:d6:d9:05:d0:1f:23:c4:d7:2a:11:67 maggie@moria
|
|
$
|
|
</screen>
|
|
</para>
|
|
|
|
<para>
|
|
Now <command>ssh</command> is ready to run.
|
|
</para>
|
|
<INDEXTERM startref="ssh.ssh.clients" class=endofrange>
|
|
</sect3>
|
|
|
|
<sect3 id="X-087-2-features.ssh.using"><title>Using ssh</title>
|
|
<para>
|
|
<INDEXTERM id="ssh.command.running" class=startofrange><PRIMARY>ssh command</PRIMARY><SECONDARY>running clients</SECONDARY></INDEXTERM>
|
|
We should now have the <command>ssh</command> command and it's associated
|
|
programs installed and ready to run. Let's now take a quick look at how to
|
|
run them.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm><primary>slogin command</primary></indexterm>
|
|
<INDEXTERM><PRIMARY>fingerprints</PRIMARY></INDEXTERM>
|
|
<INDEXTERM><PRIMARY>key fingerprints</PRIMARY></INDEXTERM>
|
|
First, we'll try a remote login to a host. We can use the <command>slogin</command> program in much the same way as we used the <command>rlogin</command>
|
|
program in our example earlier in the book. The first time you attempt a
|
|
connection to a host, the <command>ssh</command> client will retrieve the
|
|
public key of the host and ask you to confirm its identity by prompting you
|
|
with a shortened version of the public key called a
|
|
<command>fingerprint</command>.
|
|
</para>
|
|
|
|
<para>
|
|
The administrator at the remote host should have supplied you in
|
|
advance with its public key fingerprint, which you should add to your
|
|
<filename>.ssh/known_hosts</filename> file. If the remote
|
|
administrator has not supplied you the appropriate key, you can
|
|
connect to the remote host, but <command>ssh</command> will warn you
|
|
that it does have a key and prompt you whether you wish to accept the
|
|
one offered by the remote host. Assuming that you're sure no one is
|
|
engaging in DNS spoofing and you are in fact talking to the correct
|
|
host, answer yes to the prompt. The relevant key is then stored
|
|
automatically in your <filename>.ssh/known_hosts</filename> and you
|
|
will not be prompted for it again. If, on a future connection attempt,
|
|
the public key retrieved from that host does not match the one that is
|
|
stored, you will be warned, because this represents a potential security
|
|
breach.
|
|
</para>
|
|
|
|
<para>
|
|
A first-time login to a remote host will look something like:
|
|
|
|
<screen>
|
|
$ <userinput>slogin vchianti.vbrew.com</userinput>
|
|
The authenticity of host 'vchianti.vbrew.com' can't be established.
|
|
Key fingerprint is 1024 7b:d4:a8:28:c5:19:52:53:3a:fe:8d:95:dd:14:93:f5.
|
|
Are you sure you want to continue connecting (yes/no)? <userinput>yes</userinput>
|
|
Warning: Permanently added 'vchianti.vbrew.com,172.16.2.3' to the list of/
|
|
known hosts.
|
|
maggie@vchianti.vbrew.com's password:
|
|
Last login: Tue Feb 1 23:28:58 2000 from vstout.vbrew.com
|
|
$
|
|
</screen>
|
|
</para>
|
|
<?troff .Nd 10>
|
|
<para>
|
|
You will be prompted for a password, which you should answer with the
|
|
password belonging to the remote account, not the local one. This password
|
|
is not echoed when you type it.
|
|
</para>
|
|
|
|
<para>
|
|
Without any special arguments, <command>slogin</command> will attempt to log in
|
|
with the same userid used on the local machine. You can override this
|
|
using the <literal>-l</literal> argument, supplying an alternate login name
|
|
on the remote host. This is what we did in our example earlier in the book.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm><primary>scp command</primary></indexterm>
|
|
We can copy files to and from the remote host using the <command>scp</command>
|
|
program. Its syntax is similar to the conventional <command>cp</command>
|
|
with the exception that you may specify a hostname before a filename, meaning
|
|
that the file path is on the specified host. The following example illustrates
|
|
<command>scp</command> syntax by copying a local file called
|
|
<filename>/tmp/fred</filename> to the <filename>/home/maggie/</filename> of
|
|
the remote host <emphasis role=bold>chianti.vbrew.com</emphasis>:
|
|
|
|
<screen>
|
|
$ <userinput>scp /tmp/fred vchianti.vbrew.com:/home/maggie/</userinput>
|
|
maggie@vchianti.vbrew.com's password:
|
|
fred 100% |*****************************| 50165 00:01 ETA
|
|
</screen>
|
|
</para>
|
|
|
|
<para>
|
|
Again, you'll be prompted for a password. The <command>scp</command> command
|
|
displays useful progress messages by default. You can copy a file from a
|
|
remote host with the same ease; simply specify its hostname and filepath as
|
|
the source and the local path as the destination. It's even possible to copy
|
|
a file from a remote host to some other remote host, but it is something you
|
|
wouldn't normally want to do, because all of the data travels via your host.
|
|
</para>
|
|
|
|
<para>
|
|
You can execute commands on remote hosts using the
|
|
<command>ssh</command> command. Again, its syntax is very simple. Let's
|
|
have our user <userinput>maggie</userinput> retrieve the root directory of
|
|
the remote host <emphasis role=bold>vchianti.vbrew.com</emphasis>.
|
|
She'd do this with:
|
|
|
|
<screen>
|
|
$ <userinput>ssh vchianti.vbrew.com ls -CF /</userinput>
|
|
maggie@vchianti.vbrew.com's password:
|
|
bin/ console@ dos/ home/ lost+found/ pub@ tmp/ vmlinuz@
|
|
boot/ dev/ etc/ initrd/ mnt/ root/ usr/ vmlinuz.old@
|
|
cdrom/ disk/ floppy/ lib/ proc/ sbin/ var/
|
|
</screen>
|
|
</para>
|
|
|
|
<para>
|
|
You can place <command>ssh</command> in a command pipeline
|
|
and pipe program input/output to or from it just like any other command,
|
|
except that the input or output is directed to or from the remote host
|
|
via the <command>ssh</command> connection. Here is an example of how you might
|
|
use this capability in combination with the <command>tar</command> command
|
|
to copy a whole directory with subdirectories and files from a remote host
|
|
to the local host:
|
|
|
|
<screen>
|
|
$ <userinput>ssh vchianti.vbrew.com "tar cf - /etc/" | tar xvf -</userinput>
|
|
maggie@vchianti.vbrew.com's password:
|
|
etc/GNUstep
|
|
etc/Muttrc
|
|
etc/Net
|
|
etc/X11
|
|
etc/adduser.conf
|
|
..
|
|
..
|
|
</screen>
|
|
</para>
|
|
<?troff .Nd 7>
|
|
<para>
|
|
Here we surrounded the command we will execute with quotation marks to make it
|
|
clear what is passed as an argument to <command>ssh</command> and what is used
|
|
by the local shell. This command executes the <command>tar</command>
|
|
command on the remote host to archive the <filename>/etc/</filename> directory
|
|
and write the output to standard output. We've piped to an instance of the
|
|
<command>tar</command> command running on our local host in extract mode
|
|
reading from standard input.
|
|
</para>
|
|
|
|
<para>
|
|
<INDEXTERM><PRIMARY SORTAS="ssh/authorized_keys file">.ssh/authorized_keys file</PRIMARY></INDEXTERM>
|
|
Again, we were prompted for the password. Now you can see why we encouraged
|
|
you to configure <command>ssh</command> so
|
|
that it doesn't prompt you for passwords all the time! Let's now configure
|
|
our local <command>ssh</command> client so that it won't prompt for a password
|
|
when connecting to the
|
|
<systemitem role="hostname">vchianti.vbrew.com</systemitem> host. We mentioned
|
|
the <filename>.ssh/authorized_keys</filename> file earlier; this is where
|
|
it is used. The <filename>.ssh/authorized_keys</filename> file contains the
|
|
<emphasis>public</emphasis> keys on any remote user accounts that we wish to
|
|
automatically log in to. You can set up automatic logins by copying the
|
|
contents of the
|
|
<filename>.ssh/identity.pub</filename> from the <emphasis>remote</emphasis>
|
|
account into our local <filename>.ssh/authorized_keys</filename> file. It is
|
|
vital that the file permissions of <filename>.ssh/authorized_keys</filename>
|
|
allow only that you read and write it; anyone may steal and use the
|
|
keys to log in to that remote account. To ensure the permissions are correct,
|
|
change <filename>.ssh/authorized_keys</filename>, as shown:
|
|
|
|
<screen>
|
|
$ <userinput>chmod 600 ~/.ssh/authorized_keys</userinput>
|
|
</screen>
|
|
</para>
|
|
|
|
<para>
|
|
The public keys are a long <emphasis>single</emphasis> line of plain
|
|
text. If you use copy and paste to duplicate the key into your local file,
|
|
be sure to remove any end of line characters that might have been introduced
|
|
along the way. The <filename>.ssh/authorized_keys</filename> file may contain
|
|
many such keys, each on a line of its own.
|
|
</para>
|
|
|
|
<para>
|
|
<?troff .hw information>
|
|
The <command>ssh</command> suite of tools is very powerful and there are many
|
|
other useful features and options that you will be interested in exploring.
|
|
Please refer to the manual pages and other documentation that is supplied
|
|
with the package for more information.
|
|
</para>
|
|
|
|
</sect3>
|
|
<INDEXTERM startref="ssh.command.config" class=endofrange>
|
|
<INDEXTERM startref="config.ssh.command" class=endofrange>
|
|
<INDEXTERM startref="ssh.command.running" class=endofrange>
|
|
</sect2>
|
|
|
|
<indexterm class="endofrange" startref="idx-configuringrcommands">
|
|
|
|
</sect1>
|
|
</chapter>
|
|
|
|
|
|
|