FreeBSD Operating System

Basic network access: clients

Разбить на страницы
Показывать лекцию целиком

Finally we have set up the network connections, and everything is working. What can we do with the network? In this part of the book, we'll take a look at some of the more important services that make up the application layer.

The Internet protocols perform most services with a pair of processes: a client at one end of the link that actively asks for services, and a server at the other end of the link that responds to requests and performs the requested activity. These terms are also used to describe computer systems, but here we're talking about processes, not systems. In this chapter, we'll look at the client side of things, and in Chapter 25, Basic network access: servers we'll look at the corresponding servers.

Probably the single most important network service is the Hypertext Transfer Protocol or HTTP, the service that web browsers use to access the Web. We'll look at web browsers in the next section.

The next most important service is probably the Simple Mail Transfer Protocol or SMTP, the primary service for sending mail round the Internet. There's also the Post Office Protocol or POP, which is used by systems unable to run SMTP. This topic is so important that we'll devote Chapters 26 and 27 to it.

To use a remote machine effectively, you need better access than such specialized servers can give you. The most powerful access is obviously when you can execute a shell on the remote machine; that gives you effectively the same control over the machine as you have over your local machine. A number of services are available to do this. In the olden days, you would use telnet or rlogin to log into another machine. These programs are still with us, but security concerns make them effectively useless outside a trusted local network. We'll look at them briefy on page 430.

The preferred replacement is ssh, which stands for secureshell. In fact, it's not a shell at all, it's a service to communicate with a remote shell. It encrypts the data sent over the network, thus making it more difficult for crackers to abuse. We'll look at it in detail on page 419.

Another important service is the ability to move data from one system to another. There are a number of ways of doing this. The oldest programs are rcp and ftp. These programs have the same security concerns as telnet and rlogin, though ftp still has some uses. More modern copying programs use scp, which is based on ssh. We'll look at file copy programs on page 432. In addition, rsync is a useful program for maintaining identical copies files on different systems. We'll look at it on page 437.

A some what different approach is the Network File System or NFS, which mounts file systems from another machine as if they were local. We look at NFS clients on page 441.

The World Wide Web

For the vast majority of the public, the Internet and the ) run FreeBSD. Even Microsoft runs FreeBSD on its Hotmail service (http://www.hotmail.com/), though they have frequently denied it, and for image reasons they are moving to their own software.

Web browsers

A web browser is a program that retrieves documents from the Web and displays them. The base FreeBSD system does not include a web browser, but a large number are available in the Ports Collection. All web browsers seem to have one thing in common: they are buggy. They frequently crash when presented with web pages designed for Microsoft, and in other cases they don't display the page correctly. In many cases this is due to poorly designed web pages, of course.

Currently, the most important web browsers are:

  • netscape was once the only game in town, but it's now showing its age. In addition, many web sites only test their software with Microsoft, and their bugs cause problems with netscape.
  • mozilla is derived from the same sources as netscape, but comes in source form. It has now reached the stage where it is less buggy than netscape. A number of other browsers, such as galeon and skipstone, are based on mozilla. They're all available in the Ports Collection. galeon is included in the instant-workstation port described in Chapter 6.
  • konqueror is included with the KDE port.
  • Opera is a new browser that some people like. The version in the Ports Collection is free, but it makes up for it by giving you even more advertisements than the web pages give you anyway. You can buy a version that doesn't display the advertisements.
  • lynx is a web browser for people who don't use X. It displays text only.
  • You may note two omissions from this list. Microsoft's Internet Explorer is not available for FreeBSD. Not many people have missed it. Also, mosaic, the original web browser, is now completely obsolete, and it has been removed from the Ports Collection.

    In addition to these browsers, StarOffice and OpenOffice include integrated browsers. You may find you prefer them.

    This book does not deal with how to use a web browser: just about everybody knows how to use one. You can also get help from just about any browser; just click on the text or icon marked Help or ?.

    ssh

    ssh is a secure shell, a means of executing programs remotely using encrypted data transfers. There are a number of different implementations of ssh: there are two different protocols, and the implementations are complicated both by bugs and license conditions. FreeBSD comes with an implementation of ssh called OpenSSH, originally developed as part of the OpenBSD project.

    Using ssh is simple:

    $ ssh freebie
    The authenticity of host 'freebie.example.org (223.147.37.1)' can't be established.
    DSA key fingerprint is 08:f7:c4:14:48:0b:14:06:0e:2c:93:4b:1f:f6:ce:b5.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added 'freebie.example.org' (DSA) to the list of known hosts.
    grog@freebie.example.org's password:    as usual, doesn't echo
    Last login: Mon May 13 14:21:11 2002
    Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
    The Regents of the University of California. All rights reserved.
    FreeBSD 5.0-RELEASE (FREEBIE) #3: Sun Jan 5 13:25:02 CST 2003
    
    Welcome to FreeBSD!
    $ tty
    /dev/ttyp3
    $
    

    Once you get this far, you are connected to the machine in almost the same manner as if you were directly connected. This is particularly true if you are running X. As the output of the tty command shows, your "terminal" is a pseudo-tty or pty (pronounced "pity"). This is the same interface that you have with an xterm.

    It's worth looking in more detail at how the connection is established:

  • The first line (The authenticity...) appears once ssh has established preliminary contact with the remote system. It indicates that you're connected, but that the local system has no information about the remote system. Theoretically you could be connected to a different machine masquerading as the machine you want to connect to. ssh saves the fingerprint in ~/.ssh/known_hosts and checks it every time you connect to that machine thereafter.
  • The reference to DSA keys indicates that ssh is using the ssh Version 2 protocol. We'll look at the differences between the protocols below.
  • The password prompt is for the same password as you would see locally. The slightly different format is to clarify exactly which password you should enter. Again, a number of exploits are possible where you might find yourself giving away a password to an intruder, so this caution is justified.
  • When you log in via ssh, there's a chance that your TERM environment variable is set incorrectly. See table 7.3 on page 130 for more details. Remember that TERM describes the display at your end of the link. There is no display at the other end, but the other end needs to know the termcap parameters for your display. If you're running an xterm, this shouldn't be a problem: the name xterm propagates to the other end. If you're using a character-oriented display (/dev/ttyvx), however, your TERM variable is probably set to cons25, which many systems don't know. If systems refuse to start full-screen modes when you connect from a virtual terminal, try setting the TERM variable to ansi.

    To exit ssh, just log out. If you run into problems, however, like a hung network, you can also hit the combination Enter ~. Enter, which always drops the connection.

    Access without a password

    Sending passwords across the Net, even if they're encrypted, is not a complete guarantee that nobody else can get in: there are a number of brute-force ways to crack an encrypted password. To address this issue, ssh has an access method that doesn't require passwords: instead it uses a technique called public key cryptography. You have two keys, one of which you can give away freely, and the other of which you guard carefully. You can encrypt or decrypt with either key: data encrypted with the public key can be decrypted with the private key, and data encrypted with the private key can be decrypted with the public key.

    Once you have these keys in place, you can use the challenge-response method for authentication. To initiate an ssh connection, ssh sends your public key to the sshd process on the remote system. The remote system must already have a copy of this key. It uses it to encrypt a random text, a challenge, which it sends back to your system. The ssh process on your system decrypts it with your private key, which is not stored anywhere else, and sends the decrypted key back to the remote sshd. Only your system can decode the challenge, so this is evidence to the remote sshd that it's really you.

    By default, the private key for Version 1 of the protocol is stored in the file ~/.ssh/identity, and the public key is stored in the file ~/.ssh/identity_pub. For Version 2, you have a choice of two different encryption schemes, DSA and RSA. The corresponding private and public keys are stored in the files ~/.ssh/id_dsa, ~/.ssh/id_dsa.pub, ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub respectively. If you have the choice between DSA key sand RSA keys for protocol Version 2, use DSA keys, which are considered somewhat more secure. You still should have an RSA key pair in case you want to connect to a system that doesn't support DSA keys.

    There's still an issue of unauthorized local access, of course. To ensure that somebody doesn't compromise one system and then use it to compromise others, you need a kind of password for your private keys. To a void confusion, ssh refers to it as a passphrase. If ssh finds keys in the ~/.ssh directory, it attempts to use them:

    $ ssh hub
    Enter passphrase for key '/home/grog/.ssh/id_rsa':    (no echo)
    Last login: Sat Jul 13 17:27:33 2002 from wantadilla.lemis
    Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
         The Regents of the University of California. All rights reserved.
    FreeBSD 5.0-STABLE (HUB) #7: Thu Jun 26 12:44:34 PDT 2003
    (etc)
    

    Creating and distributing keys

    You create keys with the program ssh-keygen. Here's an example of generating all three keys:

    $ ssh-keygen -t rsa1
    Generating public/private rsa1 key pair.
    Enter file in which to save the key (/home/grog/.ssh/identity):  (ENTER pressed)
    Enter passphrase (empty for no passphrase):                      (no echo)
    Enter same passphrase again:                                     (no echo)
    Your identification has been saved in /home/grog/.ssh/identity.
    Your public key has been saved in /home/grog/.ssh/identity.pub.
    The key fingerprint is:
    02:20:1d:50:78:c5:7c:56:7b:1d:e3:54:02:2c:99:76 grog@bumble.example.org
    $ ssh-keygen -t rsa
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/grog/.ssh/id_rsa):    (ENTER pressed)
    Enter passphrase (empty for no passphrase):                      (no echo)
    Enter same passphrase again:                                     (no echo)
    Your identification has been saved in /home/grog/.ssh/id_rsa.
    Your public key has been saved in /home/grog/.ssh/id_rsa.pub.
    The key fingerprint is:
    95:d5:01:ca:90:04:7d:84:f6:00:32:7a:ea:a6:57:2d grog@bumble.example.org
    $ ssh-keygen -t dsa
    Generating public/private dsa key pair.
    Enter file in which to save the key (/home/grog/.ssh/id_dsa):    (ENTER pressed)
    Enter passphrase (empty for no passphrase):                      (no echo)
    Enter same passphrase again:                                     (no echo)
    Your identification has been saved in /home/grog/.ssh/id_dsa.
    Your public key has been saved in /home/grog/.ssh/id_dsa.pub.
    The key fingerprint is:
    53:53:af:22:87:07:10:e4:5a:2c:21:31:ec:29:1c:5f grog@bumble.example.org
    

    Before you can use these keys, you need to get the public keys on the remote site in the file ~/.ssh/authorized_keys. Older versions of ssh used a second file, ~/.ssh/authorized_keys2, for protocol Version 2, but modern versions store all the keys in the one file ~/.ssh/authorized_keys. There are a number of ways to get the keys in these files. If you already have access to the machine (via password-based authentication, for example), you can put them there yourself. Typically, though, you'll have to get somebody else involved. To make it easier, the public keys are in ASCII, so you can send them by mail. The three public keys generated above look like this:

    10243511012428427427480334544982386682254123065784505204062211656732932064601995
    56751223553035331118710873315456577313425763305854786629592671460454493321979564
    51897683927631476817528590966739503979593649232357835172621038275643667609041147
    5643317216 92291413130012157442638303275673247163400686283060339457790686649
     grog@bumble.example.org
    ssh-dss AAflAB3NzaC1kc3MaflACEAIltWeRXnqD9HqpLn5kugPSWHicJiu1r0I9dHg8F5m2EpmupyR
    YSmDzscAcsxifo50+1yXk3Vf4P1+EDsAwkyqFlujuMVeKoTYcOi1yrnLDWIDiAeIzt1BQ6ON^XqxwWKC
    q1eo1tXxOrTxw84VboHUuq4XFdt+yPJs8QdxLhj+jAAAAFQC1JL+tU19+UR+c45JGom6ae29d7wAAAIA
    vNgdN6rTitMjDCglN7Rq3/8WgI1kzh20XURbCe1n2yYsFifcImKb0sUYD2qsB5++gogzsse2IxyIECRC
    uyCOOFXIQ7WqkvjTp/T+fuwGPIlho8eeNDRKKABUhHjkuApnoYLIC1O5uyciJ+dIbGaRtGFJr0da7Klk
    jOLkiv3sR1gAAAIAwgKfWsRSQJyRZTkKGIHxn3EWTVSicnIRYza+HTaMuMFHMTkNMZBjhei6EoCFpV9B
    1QB9MlIZgf6WXM2DlmtdUbpm7KFA669/LZT2LvxbtGP/B++7s0PMs0AgKrKgUxnhVweufMZlPvPPPOz4
    QS1ZZ5kYhN+lu0S8yuioXYNlDtA== grog@bumble.example.org
    ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA1/W3oa1ZEs58KRWMzsrZWMXzPfwoqQ+Z59p6SJlzhevs
    XG1PAVWra2wcRz1utKFBjkDpJfEe+09L7h8VAx1aYCHji50tKI8F8YT8PuWGH+UqF/37Wl292SsXsb8g
    80yyymSfxgOM/HegvOuHQu46MfaPj9ddfcgY06z3ufcmXts= grog@bumble.example.org
    

    In the original, each key is on a single line.

    Obviously you don't want anybody messing with your authorized keys files, so ssh requires that the files belong to you and are only writeable by you. These two files typically contain multiple keys; to add a new one, just append it to the end of the file. For example, if you receive a newkey and store it in the file newkey, copy it like this:

    $ cat newkey >> ~/.ssh/authorized_keys
    

    Authenticating automatically

    Having to supply the passphrase can become a nuisance and even a serious problem. If you want to run ssh from scripts, it may not even be possible to supply the passphrase. ssh has another feature available here: it has an authentication agent that keeps track of the keys.

    The authentication agent is called ssh-agent, and you add keys with ssh-add. Due to the manner in which it is started, ssh-agent needs to be the ancestor of the shell you are running, and of the ssh-add command. Otherwise you see error messages like this:

    $ ssh-agent
    SSH_AUTH_SOCK=/tmp/ssh-cwT9aBbV/agent.42902; export SSH_AUTH_SOCK;
    SSH_AGENT_PID=42903; export SSH_AGENT_PID;
    echo Agent pid 42903;
    $ ssh-add
    Could not open a connection to your authentication agent.
    

    To solve this problem, execute the agent in your current environment with eval, then run ssh-add:

    $ eval ‘ssh-agent’
    $ ssh-add
    Enter passphrase for /home/grog/.ssh/id_rsa: (enterthepassphrase)
    Identity added: /home/grog/.ssh/id_rsa (/home/grog/.ssh/id_rsa)
    Identity added: /home/grog/.ssh/id_dsa (/home/grog/.ssh/id_dsa)
    Identity added: /home/grog/.ssh/identity (grog@zaphod.example.org)
    

    You can use ssh-add's -l flag to list which keys the authentication agent currently knows about:

    $ ssh-add -l
    1024 02:20:1d:50:78:c5:7c:56:7b:1d:e3:54:02:2c:99:76 grog@zaphod.example.org (RSA1)
    1024 95:d5:01:ca:90:04:7d:84:f6:00:32:7a:ea:a6:57:2d /home/grog/.ssh/id_rsa (RSA)
    1024 53:53:af:22:87:07:10:e4:5a:2c:21:31:ec:29:1c:5f /home/grog/.ssh/id_dsa (DSA)
    

    If you're using a Bourne-style shell such as bash, you can automate a lot of this by putting the following commands in your .bashrc or .profile file:

    if tty >/dev/null; then
      ssh-add -l > /dev/null
      if [ $? -ne 0 ]; then
        eval 'ssh-agent’
      fi
    fi
    

    This first uses the tty command to check if this is an interactive shell, then checks if you already have an authentication agent. If it doesn't, it starts one. Don't start a new authentication agent if you already have one: you'd lose any keys that the agent already knows. This script doesn't add keys, because this requires your intervention and could be annoying if you had to do it every time you start a shell.

    Setting up X to use ssh

    If you work with X, you have the opportunity to start a large number of concurrent ssh sessions. It would be annoying to have to enter keys for each session, so there's an alternative method: start X with an ssh-agent, and it will pass the information on to any xterms that it starts. Add the following commands to your .xinitrc:

    eval 'ssh-agent’
    ssh-add < /dev/null
    

    When you run ssh-add in this manner, without an input file, it runs a program to prompt for the passphrase. By default it's /usr/X11R6/bin/ssh-askpass, but you can change it by setting the SSH_ASKPASS environment variable. /usr/X11R6/bin/ssh-askpass opens a window and prompts for a passphrase. From then on, anything started under the X session will automatically inherit the keys.

    ssh tunnels

    Tunneling is a technique for encapsulating an IP connection inside another IP connection. Why would you want to do that? One reason is to add encryption to an otherwise unencrypted connection, such as telnet or POP. Another is to get access to a service on a system that does not generally supply this service to the Internet.

    Let's consider using might have the following parameters:

    (рис 24.1)

    But what if the server is firewalled from the global Internet, so you can't access it directly? That's when you need the ssh tunnel. The ssh tunnel creates a local connection at each end and a separate secure connection across the Internet:

    (рис 24.2)

    The ssh connection is shown in fixed italic font. It looks just like any other ssh connection. The differences are the local connections at each end: instead of talking to presto port 80 (http), you talk to port 4096 on your local machine. Why 4096? It's your choice; you can use any port above 1024. If you're on andante, you can set up this tunnel with the command:

    $ ssh -L 4096:presto.example.org:80 presto.example.org
    

    To do the same thing from the presto end, you'd set up a reverse tunnel with the –R option:

    $ ssh -R 4096:presto.example.org:80 andante.example.org
    

    These commands both set up a tunnel from port 4096 on . You still need to supply the name of the system to connect to; it doesn't have to be the same. For example, you might not be able to log in to the web server, but you could access your machine back home, and it has access to the web server. In this case, you could connect to your machine at home:

    $ ssh -L 4096:presto.example.org:80 freebie.example.org
    

    In addition to setting up the tunnel, ssh can create a normal interactive session. If you don't want this, use the -f option to tell ssh to go into the background after authentication. You can also specify a command to execute, but this is no longer necessary for protocol version 2. If you don't want to execute a command, use the -N option:

    $ ssh -L 4096:presto.example.org:80 presto.example.org -f –N
    

    If you're running protocol version 1, you can use sleep with an appropriately long timeout, in this example 1 hour:

    $ ssh -L 4096:presto.example.org:80 presto.example.org -f sleep 3600
    

    Tunneling X

    Running X clients on the remote machine is special enough that ssh provides a special form of tunneling to deal with it. To use it, you must tell ssh the location of an .Xauthority file. Do this by adding the following line to the file ~/.ssh/environment:

    XAUTHORITY=/home/yourname /.Xauthority
    

    The name must be in fully qualified form: ssh does not understand the shortcut ~/ to represent your home directory. You don't need to create ~/.Xauthority, though: ssh can do that for you.

    Once you have this in place, you can set up X tunneling in two different ways. To start it from the command line, enter something like:

    $ ssh -X -f website xterm
    

    As before, the -f option tells ssh to go into the background. The -X option specifies X tunneling, and ssh runs an xterm on the local machine. The DISPLAY environment variable points to the (remote) local host:

    $ echo $DISPLAY
    localhost:13.1
    

    Other uses of tunnels

    Tunneling has many other uses. Another interesting one is bridging networks. For example, http://unix.za.net/gateway/documentation/networking/vpn/fbsd.html describes how to set up a VPN (Virtual Private Network) using User PPP and an ssh tunnel.

    Configuring ssh

    It can be a bit of a nuisance to have to supply all these parameters to ssh, but you don't have to: you can supply information for frequently accessed hosts in a configuration file. On startup, ssh checks for configuration information in a number of places. It checks for them first in the command line options, then in you configuration file ~/.ssh/config, and finally in the system-wide configuration file /etc/ssh/ssh_config. The way it treats duplicate information is pretty much the opposite of what you'd expect: unlike most other programs, options found in a configuration file read in later do not replace the options found in an earlier file. Options on the command line replace those given in configuration files.

    In practice, such conflicts happen less often than you might expect. The file /etc/ssh/ssh_config, the main configuration file for the system, normally contains only comments, and by default you don't even get a local ~/.ssh/config.

    sshconfig can contain a large number of options. They're all described in the man page ssh_config(8) ,but it's worth looking at some of the more common ones. In this section we'll look at some of the more common configuration options.

  • The entry Host is special: the options that follow, up to the end of the file or the next following Host argument, relate only to hosts that match the arguments on the Host line.
  • Optionally, ssh can compress the data streams. This can save a lot of traffic, but it can also increase CPU usage, so by default it is disabled. You can do this by passing the -C flag to ssh, but you can also do so by setting Compression yes in the configuration file.
  • You can escape out of an ssh session to issue commands to ssh with the EscapeChar. By default it's the tilde character, ~ Other programs, notably rlogin, use this character as well, so you may want to change it. You can set this value from the ssh command line with the -e option.
  • To forward an X11 connection, as shown above, you can also set the ForwardX11 variable to yes. This may be useful if you frequently access a remote machine and require X forwarding. This also sets the DISPLAY environment variable correctly to go over the secure channel.
  • By default, ssh sends regular messages to the remote sshd server to check if the remote system has gone down. This can cause connections to be dropped on a flaky connection. Set the KeepAlive option to no to disable this behavior.
  • Use the LocalForward parameter to set up a tunnel. The syntax is similar to that of the -L option above: on andante, instead of the command line:
    $ ssh -L 4096:presto.example.org:80 presto.example.org
    

    You would put the following in your ~/.ssh/config:

    host presto.example.org
    LocalForward 4096 presto.exanple.org:80
    

    Note that the first port is separated from the other two parameters by a space, not a colon.

  • Similarly, you can set up a reverse tunnel with the RemoteForwar parameter. On presto, instead of the command line:
    $ ssh -R 4096:presto.example.org:80 andante.example.org
    

    you would put the following in your ~/.ssh/config:

    host andante.example.org
    RemoteForward 4096 presto.example.org:80
    
  • By default, ssh uses password authentication if it can't negotiate a key pair. Set PasswordAuthentication to no if you don't want this.
  • Normally ssh connects to the server on port 22 (ssh). If the remote server uses a different port, specify it with the Port keyword. You can also use the -p option on the ssh command line.
  • By default, ssh attempts to connect using protocol 2, and if that doesn't work, it tries to connect using protocol 1. You can override this default with the Protocol keyword. For example, to reverse the default and try first protocol 1, then protocol 2, you would write:
    Protocol 1,2
    
  • By default, ssh refuses to connect to a known host if its key fingerprint changes. Instead, you must manually remove the entry for the system from the ~/.ssh/known_hosts or ~/.ssh/known_hosts2 file. This can indicate that somebody is faking the remote machine, but more often it's because the remote machine has really changed its host key, which it might do at every reboot. If this gets on your nerves, you can add this line to your configuration file:
    StrictHostKeyChecking no
    

    This doesn't stop the warnings, but ssh continues:

    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    @    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!    @
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
    Someone could be eavesdropping on you right now (man-in-the-middle attack)!
    It is also possible that the DSA host key has just been changed.
    The fingerprint for the DSA key sent by the remote host is
    95:80:4c:fb:cc:96:1b:36:c5:c9:2b:cb:d1:d4:16:68.
    Please contact your system administrator.
    Add correct host key in /home/grog/.ssh/known_hosts2 to get rid of this message.
    Offending key in /home/grog/.ssh/known_hosts2:39
    
  • ssh assumes that your user name on the remote system is the same as the name on the local system. If that's not the case, you can use the User keyword to specify the remote user name. Alternatively, you can use the format:
    $ ssh newuser@remotehost.org
    
  • Summary of files in ~/.ssh

    In addition to the files we have discussed, you will find two other files in the ~/.ssh directory:

  • known hosts contains the key fingerprints of all hosts to which you have connected. The example on page 419 shows how ssh adds a key.
  • randomseed is a seed used to generate the keys.
  • In summary, then, you can expect the following files in your ~/.ssh:

    drwx------  2  grog  grog   512  Jan  18  21:04  .                 directory
    -rw-r--r--  1  grog  grog  1705  Oct  26   1999  authorized keys   keys
    -rw-r--r--  1  grog  grog   844  Jan  27  22:18  authorized keys2  keys, Version 2 only
    -rw-r--r--  1  grog  grog    25  Oct  20  01:35  environment       environment for sshd
    -rw-------  1  grog  grog   736  Jul  19  15:40  id dsa            DSA private key
    -rw-r--r--  1  grog  grog   611  Jul  19  15:40  id dsa.pub        DSA public key
    -rw-------  1  grog  grog   951  Jul  19  15:40  id rsa            RSA private key
    -rw-r--r--  1  grog  grog   231  Jul  19  15:40  id rsa.pub        RSA public key
    -rw-------  1  grog  grog   536  Jul  19  15:39  identity          RSA1 private key
    -rw-r--r--  1  grog  grog   340  Jul  19  15:39  identity.pub      RSA1 public key
    -rw-------  1  grog  grog  1000  Jul  25   1999  known hosts       list of known hosts
    -rw-------  1  grog  grog   512  Jul  25   1999  random seed       for key generation
    

    Note particularly the permissions and the ownership of the files and the directory itself. If they are wrong, ssh won't work, and it won't tell you why not. In particular, the directory must not be group writeable.

    Troubleshooting ssh connections

    A surprising number of things can go wrong with setting up ssh connections. Here are some of the more common ones:

  • After some delay, you get the message:
    ssh: connect to address 223.147.37.76 port 22: Operation timed out
    

    This probably means that the remote host is down, or that you can't reach it due to network problems.

  • You get the message:
    ssh: connect to address 223.147.37.65 port 22: Connection refused
    
    This means that the remote host is up, but no sshd is running.
  • You have set up keys, but you still get a message asking for a password.

    This can mean a number of things: your ssh-agent isn't running, you haven't added the keys, the other end can't find them, or the security on the keys at the other end is incorrect. You can check the first two like this:

    $ ssh-add -l
    Could not open a connection to your authentication agent.
    

    This message means that you haven't run ssh-agent. Do it like this:

    $ eval ‘sh-agent’
    Agent pid 95180
    $ ssh-add -l
    The agent has no identities.
    $ ssh-add
    Enter passphrase for /home/grog/.ssh/id_rsa:    no echo
    Identity added: /home/grog/.ssh/id_rsa (/home/grog/.ssh/id_rsa)
    Identity added: /home/grog/.ssh/id_dsa (/home/grog/.ssh/id_dsa)
    Identity added: /home/grog/.ssh/identity (grog@freebie.lemis.com)
    $ ssh-add -l
    1024 02:20:1d:50:78:c5:7c:56:7b:1d:e3:54:02:2c:99:76 grog@zaphod.example.org (RSA1)
    1024 95:d5:01:ca:90:04:7d:84:f6:00:32:7a:ea:a6:57:2d /home/grog/.ssh/id_rsa (RSA)
    1024 53:53:af:22:87:07:10:e4:5a:2c:21:31:ec:29:1c:5f /home/grog/.ssh/id_dsa (DSA)
    

    In this case, all three keys are set correctly. If you have, say, only an RSA1 (protocol Version 1) key, and the other end doesn't support protocol Version 1, ssh will ask for a password.

  • You get a message like this:
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    @    WARNING: REMDTE HOST IDENTIFICATION HAS CHANGED!    @
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
    Someone could be eavesdropping on you right now (man-in-the-middle attack)!
    It is also possible that the DSA host key has just been changed.
    The fingerprint for the DSA key sent by the remote host is
    95:80:4c:fb:cc:96:1b:36:c5:c9:2b:cb:d1:d4:16:68.
    Please contact your system administrator.
    Add correct host key in /home/grog/.ssh/known_hosts2 to get rid of this message.
    Offending key in /home/grog/.ssh/known_hosts2:39
    

    There are two possible reasons for this message. As the message states, one is that somebody is trying to intercept the connection, and the other one is that the remote system has changed its host key. The latter is by far the more common. To fix this problem, you have two choices:

  • Edit your ~/.ssh/known_hosts2 file and remove references to the remote system. The message suggests changing line 39, but you might have more than one key for this system in this file. If one is wrong, there's a good chance that any others will be too, so you should remove all references.
  • Add the following line to your ~/.ssh/config file:
    StrictHostKeyChecking no
    

    It doesn't remove the warning, but it allows you to connect anyway.

  • ssh includes debugging options that may help debug problems setting up connections. Use the -v option, up to three times, to get ssh to display largely undocumented information about what is going on. The output is pretty verbose; with three -v options you get nearly 200 lines of information.

    telnet

    As mentioned above, telnet is an older, unencrypted program that connects to a shell on a remote system. You might find it of use when connecting to a system that doesn't have ssh. Be very careful not to use valuable passwords, since they are transmitted in the clear. Apart from that, you use it pretty much in the same way as ssh:

    $ telnet freebie
    Trying 223.147.37.1...
    Connected to freebie.example.org.
    Escape character is '^]'.
    login: grog
    Password:    (no echo)
    
    FreeBSD/i386 (wantadilla.example.org) (ttypj)
    Last login: Mon Oct 14 17:51:57 from sydney.example.org
    Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
        The Regents of the University of California.  All rights reserved.
    
    FreeBSD 5.0-RELEASE (FREEBIE) #0: Tue Dec 31 19:08:24 CST 2002
    
    You have new mail.
    If I have seen farther than others, it is because I was standing on the
    shoulders of giants.
      -- Isaac Newton
    
    In the sciences, we are now uniquely privileged to sit side by side
    with the giants on whose shoulders we stand.
      -- Gerald Holton
    
    If I have not seen as far as others, it is because giants were standing
    on my shoulders.
      -- Hal Abelson
    
    In computer science, we stand on each other's feet.
      -- Brian K. Reid
    $ tty
    /dev/ttyp9
    $
    

    Once you get this far, you are connected to the machine in an almost identical manner as if you were directly connected. This is particularly true if you are running X. As the output of the tty command shows, your "terminal" is a pseudo-tty or pty (pronounced "pity"). This is the same interface that you will have with an xterm.

    It's worth looking in more detail at how the connection is established:

  • The first line (Trying...)appears as soon as telnet has resolved the IP address.
  • The next three lines appear as soon as it has a reply from the other end. At this point, there can be a marked delay before telnet continues. telnet performs a reverse DNS lookup to find the name of your system. If you get a delay here, it could be an indication that your reverse lookup is not working correctly. After DNS times out, it will continue normally, but the delay is a nuisance.
  • Logging in is almost exactly the same as logging in locally. Normally you won't be able to log in directly as root, unless you have set /dev/ptyx as secure in your /etc/ttys (see page 197 for further details). It's not a good idea to set your ptys as secure. Use su instead if you want to become root.
  • When you log in via telnet, there's a good chance that your TERM environment variable will be set incorrectly. See Table 7-3 on page 130 for more details. TERM describes the display at your end of the display, not the other end. If you're running an xterm, this shouldn't be a problem: probably the name xterm will propagate to the other end. If you're using a character-oriented display (/dev/ttyvx), however, your TERM variable will probably be set to cons25, which many systcodes don't know. If the rcodeote systcode refuses to start programs in full-screen modes, try setting the TERM variable to ansi.

    To exit telnet, you just log off. If you run into problems, however, like a hung network, you can also hit Ctrl-] to enter telnet command mode, and from there enter quit:

    $ ^]
    telnet> quit
    $
    

    If you hit Ctrl-] by accident, just hit Enter to return to the telnet session.

    Secure telnet

    Recent releases of FreeBSD telnet include a secure connection option. You can recognize it by the different messages that appear when you connect:

    $ telnet freebie
    Trying 223.147.37.1...
    Connected to freebie.example.org.
    Escape character is '^]'.
    Trying SRA secure login:
    User (grog):
    Password:
    [SRA accepts you ]
    

    There's no particular reason to use this version of telnet; it's non-standard, and you're still better off with ssh.

    Using telnet for other services

    The way we have used telnet so far, it connects to the default port, telnet (number 23, as you can see in the file /etc/services). This isn't the only possibility, though: you can tell telnet which port to connect to. In Chapter 27, Electronic mail: servers, we'll see how to communicate with sendmail using telnet on port smtp page 502, and how to communicate with POP on port pop, page 504. There are many other such uses.

    Copying files

    The other basic function involves copying files between systems. The traditional tools are ftp and rcp. Neither use encryption, so it's preferable to use scp, a variant of ssh. Nevertheless, ftp has its uses. About the only use for rcp is on systems that don't support scp, or systems where security is not an issue, and scp is so slow that it's not practical. The good news: you use rcp in pretty much the same manner as scp: scp was designed to be compatible with rcp, so you don't need to learn anything else if you want to use it.

    scp

    scp is a variant of ssh used for remote copying. The same access considerations apply as for ssh. The syntax for copying is similar to the syntax used by NFS: to copy a file /var/log/messages from presto to the file prestomessages on the local machine, you might enter:

    $ scp presto:/var/log/messages prestomessages
    

    As with ssh, if you need to authenticate as a different user, you can use the form user@system.scp does not support the -l option to specify the user name.

    scp has a number of options reminiscent of cp:

  • • Use the -p option to preserve modification times and permissions where possible. Note that this means you can't use ssh's -p option to specify an alternative port. scp uses the -P option for this instead.
  • • Use the -r option to recursively copy directories. You don't have to supply full path names to scp; you can write things like:
  • $ scp remotehost:file .
    

    This looks for a file called file in your home directory on the remote machine and copies it to your current local directory. Note the difference: there is no way for scp to know a different remote directory, so relative paths are always relative to the home directory on that machine.

    ftp

    ftp is the Internet File Transfer Program, and is the standard way to transfer large files long distances across the Net. It works for small files and short distances too, but you may find that scp or NFS are better alternatives in these areas.

    One serious drawback in duplicating files across the net is that you need to have permission to access the remote system. Traditionally, you need a user ID to access a system. Of course, the file server could have a specific user ID without a password, but that would throw the system open to attack from crackers. ftp solves this problem by recognizing the special user ftp. This user name used to be anonymous, but it turned out to be a problem to spell. ftp servers still accept the name anonymous as well. Login is special: you don't need a password, but by convention, to help the system administrators with their bookkeeping, you should enter your real user ID in place of the password when logging in as ftp.A typical session might look like:

    $ ftp ftp.freebsd.org
    Connected to ftp.beastie.tdk.net.
    cd 220 ftp.beastie.tdk.net FTP server (Version 6.00LS) ready.
    331 Guest login ok, send ident as password.
    Password:    password does not echo
    230 Guest login ok, access restrictions apply.
    Remote system type is UNIX.
    Using binary mode to transfer files.
    ftp> bin    to ensurebinary transfer
    200 Type set to I.
    230- The FreeBSD mirror at Tele Danmark Internet.
    Moremessagesomitted Name (grog): ftp
    331 Guest login ok, send your email address as password.
    ftp> cd /pub/FreeBSD/ports/distfiles
    250 CWD command successful.
    ftp> get xtset-1.Ctar.gz
    local: xtset-1.0.tar.gz remote: xtset-1.0.tar.gz
    229 Entering Extended Passive Mode (|||58059|)
    150 Opening BINARY mode data connection for 'xtset-1.0.tar.gz'   (4239 bytes).
    100%  |*************************************|    4239    5.49 KB/s  00:00
    226 Transfer complete.
    4239 bytes received in 00:00 (5.49 KB/s)
    ftp> ^D
    221 Goodbye.
    

    There are a number of things to note about this transfer:

  • The server may have multiple names, and the one you use may not be its canonical name (the name specified in the server's DNS A record—see page 363). By convention, the first part of the name of an , but the canonical name of the server is ftp://ftp.beastie.tdk.net.
  • Some versions of ftp transmit in ASCII mode by default: they change every incidence of the ASCII line feed character (the C language constant \n) to the sequence \r\n (they prep end an ASCII carriage return character). This permits you to print the results on normal printers, but makes a terrible mess of binary files. Transmitting in binary form always works. As the message shows, the FreeBSD ftp server uses binary mode, but it doesn't harm to enter the bin command. The message Type set to I. is ftp's way of telling you that it has set binary transmission mode.
  • The line of **** is an indication of the progress of the transfer. It's specific to BSD; other ftp clients don't show you anything here.
  • Specifying file names as URIs

    This transmission is fairly typical, and it's the traditional way to do it. FreeBSD has another method, though, which can be of use: instead of the interactive approach, you can specify the file name as a URI, and you can use ftp to download HTTP documents from a web server. For example, the last transfer can be simplified to:

    $ ftp ftp://ftp.freebsd.org/pub/FreeBSD/ports/distfiles/xtset-l.O.tar.gz
    Connected to ftp.beastie.tdk.net.
    220 ftp.beastie.tdk.net FTP server (Version 6.00LS) ready.
    331 Guest login ok, send your email address as password.
    ...
    230 Guest login ok, access restrictions apply.
    Remote system type is UNIX.
    Using binary mode to transfer files.
    200 Type set to I.
    250 CWD command successful.
    250 CWD command successful.
    250 CWD command successful.
    250 CWD command successful.
    local: xtset-1.0.tar.gz remote: xtset-1.0.tar.gz
    229 Entering Extended Passive Mode (|||59779|)
    150 Opening BINARY mode data connection for 'xtset-1.0.tar.gz' (4239 bytes).
    100%  |*************************************|  4239  5.82 KB/s  00:00
    226 Transfer complete.
    4239 bytes received in 00:00 (5.81 KB/s)
    Goodbye.
    

    Note that this method implies anonymous ftp: you don't have to log in. In the same way, you can download a web page like this:

    $ ftp http://www.FreeBSD.org/index.litml
    Requesting http://www.FreeBSD.org/index.html
    100%  |*************************************| 26493  12.20 KB/s 00:02
    26493 bytes retrieved in 00:02 (12.17 KB/s)
    

    Note that in this case you can't just specify the URI as http://www.FreeBSD.org: you must specify the real file name.

    Other ftp commands

    ftp has about sixty commands, some of which can be of use. We'll look at the most useful commands in the following sections.

    mget

    ftp> ls
    200 PORT command successful.
    150 Opening ASCII mode data connection for /bin/ls.
    -rw-rw-r--  1  117  1001    43367  Nov   1  02:37  gcc-2.5.0-2.5.2.diff.gz
    -rw-rw-r--  1  117  1001     1010  Nov   1  02:37  gcc-2.5.1-2.5.2.diff.gz
    -rw-rw-r--  1  117  1001    78731  Nov  11  13:53  gcc-2.5.2-2.5.3.diff.gz
    -rw-rw-r--  1  117  1001    13931  Nov  17  09:27  gcc-2.5.3-2.5.4.diff.gz
    -rw-rw-r--  1  117  1001    76271  Nov  27  16:48  gcc-2.5.4-2.5.5.diff.gz
    -rw-rw-r--  1  117  1001     8047  Dec   3  09:22  gcc-2.5.5-2.5.6.diff.gz
    -rw-rw-r--  1  117  1001  5994481  Nov  27  16:49  gcc-2.5.5.tar.gz
    -rw-rw-r--  1  117  1001    10753  Dec  12  19:15  gcc-2.5.6-2.5.7.diff.gz
    -rw-rw-r--  1  117  1001    14726  Jan  24  09:02  gcc-2.5.7-2.5.8.diff.gz
    -rw-rw-r--  1  117  1001  5955006  Dec  22  14:16  gcc-2.5.7.tar.gz
    -rw-rw-r--  1  117  1001  5997896  Jan  24  09:03  gcc-2.5.8.tar.gz
    226 Transfer  complete.          
    ftp>
    

    Frequently you need to copy more than a single file. For example, if you currently have gcc-2.5.0 and want to get gcc-2.5.8, you will discover the following files on the file server:

    In other words, you have the choice of transferring 6 MB of software in gcc-2.5.8.tar.gz or seven incremental patch files with a total of less than 250 kB. On the other hand, copying the diffs requires typing all these long, complicated file names, so you might decide it's easier just to duplicate the whole 6 MB.

    There is an easier way: mget (multiple get) duplicates files matching a wild card. You could perform the complete transfer with:

    ftp> mget gcc-2*diff.gz
    mget gcc-2.5.0-2.5.2.diff.gz?y
    200 PORT command successful.
    150 Opening BINARY mode data connection for
        gcc-2.5.0-2.5.2.diff.gz (43667 bytes).
    226 Transfer complete.
    43667 bytes received in 19 seconds (2.298 Kbytes/s)
    mget gcc-2.5.1-2.5.2.diff.gz?n        we don't need this one
    mget gcc-2.5.2-2.5.3.diff.gz?y
    200 PORT command successful.
    150 Opening BINARY mode data connection for
      gcc-2.5.2-2.5.3.diff.gz (78731 bytes).
    226 Transfer complete.
    78731 bytes received in 33 seconds (2.835 Kbytes/s)
    ... etc
    

    prompt

    Using mget saves a lot of network bandwidth and copies the files faster, but it has one disadvantage: ftp prompts you for each file name, so you have to wait around to answer the prompts. If you don't, ftp disconnects after 15 minutes of inactivity. It would be simpler to perform all the mgets without any intervention. This is where the prompt command comes in.

    The prompt command specifies whether to issue certain prompts or not—the mget command is one example. This command is a toggle—in other words, if prompting is on, prompt turns it off, and if prompting is off, prompt turns it on. If prompting is off, the mget command in the previous example would have gone through with no interruptions.

    In the previous example, you don't really want to transfer the file gcc-2.5.1-2.5.2.diff.gz, because you don't need it to perform the patches: you can upgrade from 2.5.0 to 2.5.2 directly with the file gcc-2.5.0-2.5.2.diff.gz. On the other hand, not copying the file would mean sitting around for the duration of the transfer and answering the prompt for each file, and the file is only 1 kB long. In this case, it is reasonable to copy it as well-in other cases; you may need to consider alternatives.

    reget

    Sooner or later, you will lose a connection in the middle of a transfer. According to Murphy's law, this will usually happen with a big file, and it will be shortly before the transfer is finished. You may be able to save the day with reget, which picks up the transfer where it left off. The scodeantics are the same as for get.

    Unfortunately, not all versions of ftp have the reget command, and on many systems that do have the command, it doesn't work correctly. If you do decide to use it, you should first make a copy of the partially copied file, in case something goes wrong.

    user

    Normally, ftp attempts to log in using the user name of the user who started the ftp program. To make establishing connections easier, ftp checks for a file called .netrc when performing a login sequence. .netrc contains information on how to log in to specific systems. A typical .netrc might look like:

    machine freebie  login grog  password foo
    machine presto   login grog  password bar
    machine bumble   login grog  password baz
    machine wait     login grog  password zot
    default          login ftp   password grog@example.org
    

    Lines starting with the keyword machine specify login name (grog in this example) and password for each system. The last line is the important one: if the system is not mentioned by name, ftp attempts a login with user name ftp and password grog@example.org. Though this may be of use with systems you don't know, it causes a problem: if you want to connect to a machine without anonymous ftp, you will need to explicitly tell ftp not to attempt an auto-login. Do this with the -n option:

    $ ftp -n ftp.remote.org
    

    The .netrc file is a security risk: it contains all your passwords in readable form. Make sure it is secured so that only you can read or write it.

    ftp is not overly clear about login failures. For example,

    $ ftp ftp.tu-darmstadt.de
    Connected to ftp.tu-darmstadt.de.
    220 rs3.hrz.th-darmstadt.de FTP server (Version 4.1) ready.
    331 Password required for grog.
    530 Login incorrect.
    Login failed.
    Remote system type is UNIX.
    Using binary mode to transfer files.
    ftp>
    

    This error message is not very obvious: although you're not logged in, you still get the same prompt, and ftp produces enough verbiage that it's easy to oversee that the login attempt failed. To complete the login, use the user command:

    ftp> user ftp
    331 Guest login ok, send ident as password.
    Password:                  password does not echo
    230 Guest login ok, access restrictions apply.
    

    sftp

    sftp is yet another ssh-based program. It's designed to be as compatible as possible with ftp, so you use it in exactly the same manner. As with other ssh-related commands, you need to authenticate in an ssh-specific manner. In addition, it has an exec command, which allows you to run programs on the remote machine.

    To use sftp, the remote machine must be able to run the sftp-server server. It is normally started from sshd. See page 454 for more details.

    rsync

    Frequently you want to keep identical copies of files on different machines. You can copy them, of course, but if there are only small changes in large files, this can be relatively inefficient. You can perform this task more efficiently with rsync, which is designed to keep identical copies of files on two different systems and to optimize network bandwidth while doing so. It's in the Ports Collection. Install in the normal manner:

    # cd /usr/ports/net/rsync
    # make install
    

    By default, rsync uses ssh to perform the transfer, so you need to have ssh configured correctly. In particular, you should be using ssh-agent authentication.

    You can use rsync like scp: the syntax is compatible up to a point. For example, you could copy a file from a remote system with:

    $ rsync presto:/var/log/messages prestomessages
    

    You don't need to install rsync just for that, of course: you can do exactly the same thing with scp. rsync has one advantage over scp, how ever, even in this case. The first time you copy the file, there's no difference. But files like /var/log/messages grow at the end, and the rest doesn't change. That's an ideal situation for rsync: it uses an algorithm that recognizes common parts of files (not necessarily at the beginning) and optimizes the transfer accordingly. The first time you run the program, you might see:

    $ rsync -v /var/log/messages freebie:/var/tmp
    messages
    wrote 80342 bytes  read 36 bytes  53585.33 bytes/sec
    total size is 80255  speedup is 1.00
    $ rsync -v /var/log/messages freebie:/var/tmp
    messages
    wrote 535 bytes  read 726 bytes  840.67 bytes/sec
    total size is 80255  speedup is 63.64
    

    This example used the option -v to show details of what was transferred; otherwise you wouldn't see any output at all. The first time round, the entire file was copied, so there was no speed up. The second time, though, almost nothing needed to be copied, so the transfer was over 60 times as fast.

    Copying directory hierarchies

    rsync has a bewildering number of options for synchronizing directories. Consider the case where you maintain web pages locally, but your main web server is co-located somewhere else. After updating the local web pages, you can run a script to update the remote pages with commands like:

    rsync -LHzav --exclude=RCS --exclude="*~" ~grog/public_html/* website:htdocs/grog
    rsync -LHztpgov --exclude="*~" website:htdocs
    

    The first rsync command synchronizes the local directory ~grog/public_html to the remote directory htdocs/grog on the system website. It includes all subdirectories with the exception of the RCS directories. The second command synchronizes the top level web directory only, and not the subdirectories, many of which shouldn't be maintained on the remote site. In each case, files ending in ~ are excluded (these are normally Emacs backup files), and in the second case the RCS subdirectories are also excluded. Let's look more carefully at all those options:

  • -L copies symbolic links (which the documentation refers to as "soft links") as separate files. If you don't include this option, symbolic links to files within the directory hierarchy will work, but links outside the hierarchy may be broken (depending on whether a file of that name exists on the destination system or not). In this example, a number of files are really located elsewhere, so it makes sense to copy them as files.
  • -H is pretty much the opposite of -L: by default, rsync doesn't check whether it has already copied a file, so if it finds another link to it, it will create a new file on the remote machine. -H tells it to keep track of links and simply create another link to any file it has already copied on the destination machine. This can only work if the two links have been copied by the same invocation of rsync.
  • The option -z tells rsync to compress data. This can significantly reduce traffic.
  • The option -a ("archive") is in fact a shorthand notation for a total of seven other options. We'll see some of them below. The others are:
  • -r: copy subdirectories recursively.
  • -l: create symbolic links where necessary. In this example, it's overruled by the -L option.
  • -D: copy device nodes (only for root).
  • The other options are -p, -t, -g and -o. We don't want to copy subdirectories in the second example, so we state them explicitly. Together, they roughly correspond to the -p (preserve) option to some other copy programs.

  • The option -p tells rsync to set the permissions of the remote copy to be the same as those of the original file.
  • The option -t tells rsync to preserve the modification times of the original file on the remote copy.
  • The option -g tells rsync to set the group ownership of the remote copy to be the same as those of the original file.
  • The option -o tells rsync to set the ownership of the remote copy to be the same as those of the original file.
  • We've already seen the -v option: it gives information on what rsync is doing.
  • When copying directories with rsync, it's relatively easy to end up with the files in the wrong directory level: either they're in the parent directory, or in a subdirectory of the same name. Consider the following command to synchronize a mail folder to a laptop:

    $ cd /home/grog
    $ rsync -zHLav presto:/home/grog/Mail Mail
    

    This would seem to duplicate the directory /home/grog/Mail on the remote system to a directory of the same name on the local system. In fact, it moves the contents of the host /home/grog/Mail to /home/grog/Mail/Mail on the local machine. To do what you expect, write:

    $ rsync -zHLav presto:/home/grog/Mail .
    

    Using an rsync server

    The use of rsync that we've seen so far doesn't require a server, but it does require an ssh. rsync also offers a different means of access that uses a server, rsyncd. This method is intended more for access to systems for which you don't have a password, something like anonymous ftp.

    We'll look at setting up an rsync server on page 454. The client side is relatively simple. Use two colons when referring to the remote system. For example, you might enter:

    $ rsync freebie::
    This is freebie.example.org.  Be gentle.
    
    groggy  Greg's web pages
    tivo    TiVo staging area
    

    The first line is simply an identification message, referred to as a message of the day in the documentation. The others represent directory hierarchies that the server makes available, along with a comment about their purpose. The documentation calls them modules. As we'll see on page 454, they correspond to directories on the server machine, though the names don't need to be related.

    To find out what is in these directories, you can use the following kind of command, which specifies a particular module, but no destination:

    $ rsync freebie::groggy
    This is freebie.example.org.   Be gentle.
    drwxr-xr-x    5632 2002/10/24 12:40:38 .
    -rw-r--r--    3855 2002/03/16 13:51:12 20feb99.html
    -rw-r--r--    2363 2002/03/16 13:51:12 7mar1999.html
    -rw-r--r--    8345 2002/03/16 13:51:12 AOSS-programme-orig.html
    -rw-r--r--   11590 2002/03/16 13:51:12 AOSS-programme.html
    -rw-r--r--    1798 2002/03/16 13:51:12 BSDCon-2002.html
    -rw-r--r--    1953 2002/03/16 13:51:12 Essey-20020222.html
    ...etc
    

    To transfer a file, specify its name and a destination:

    $ rsync -v freebie::groggy/AOSS-programme.html .
    This is freebie.example.org.  Be gentle.
    
    AOSS-programme.html
    wrote 98 bytes  read 11744 bytes  23684.00 bytes/sec
    total size is 11590  speedup is 0.98
    

    This example uses the -v option to show what rsync has done; without it, there would be no output.

    If you want to transfer the entire module, use the -r or -a options we looked at above:

    $ rsync -r -v freebie::groggy .
    This is freebie.example.org.   Be gentle.
    
    receiving file list ... done
    skipping non-regular file "Images/20001111"
    20feb99.html
    7mar1999.html
    AOSS-programme-orig.html
    AOSS-programme.html
    BSDCon-2002.html
    ...etc
    

    The Network File System

    The Network File System, or NFS, is the standard way to share UNIX files across a network.

    We've already seen that UNIX file systems are accessible in a single tree by mounting them on a specific directory. NFS continues this illusion across the network.

    From a user point of view, there is little difference: you use the same mount command, and it performs what looks like the same function. For example, if system presto's system administrator wants to mount freebie's file systems, /usr and /home, he could enter:

    # mkdir    /freebie
    # mount    freebie:/  /freebie
    # mount    freebie:/usr  /freebie/usr
    # mount    freebie:/home  /freebie/home
    

    You'll note how to specify the file systems: the system name, a colon (:), and the file system name. This terminology predates URIs; nowadays, people would probably write nfs://freebie/usr.

    Note also that you don't need to create /freebie/usr and /freebie/home :assuming that the directories /usr and /home exist on once you have mounted /freebie, they will become visible.

    If you look at NFS more closely, things don't look quite as similar to disks as they do at first sight. You access local file systems via the disk driver, which is part of the kernel. You access NFS file systems via the NFS processes.

    Older implementations of NFS had a plethora of processes. If you're used to such systems, don't let the lack of processes make you think that there's something missing.

    NFS client

    You don't need any particular software to run as an NFS client, but the program nfsiod greatly improves performance. It's started at boot up time if you specify nfs_client_enable="YES" in your /etc/rc.conf, but you can also start it manually if it's not running:

    # nfsiod -n 6
    

    The parameter -n 6 tells nfsiod how many copies of itself to start. The default is four. Each nfsiod can handle a concurrent I/O request, so if you find that your performance isn't what you would like it to be, and the CPU time used by each nfsiod is similar, then you might like to increase this value. To ensure it's done automatically at boot time, add the following to /etc/sysctl.conf:

    vfs.nfs.iothreads=6
    

    We'll look at /etc/rc.conf and /etc/sysctl.conf in more detail in Chapter 29.

    Mounting remote file systems

    As we've seen, we mount NFS files with the same mount command that we use for local file systems. This is another illusion: mount is just a front-end program that determines which program to start. In the case of local file systems, it will start mount_ufs, and for NFS file systems it will start mount_nfs.

    There are a number of options you may wish to use when mounting NFS file systems. Unfortunately, the options that mount_nfs uses are not the same as the options you would use in /etcfstab. Here's an over view:

    NFS mount options
    fstab optionmount_nfs optionMeaning
    bg-bContinue attempting the mount in the background if it times out on the initial attempt. This is a very good idea in /etc/ftab, because otherwise the boot process waits until all mounts have completed. If you've just had a power failure, this can cause deadlocks otherwise.
    nfsv2-2Use NFS Version 2 protocol. By default, mount_nfs tries NFS Version 3 protocol first, and falls back to Version 2 if the other end can't handle Version 3. Don't use NFS Version 2 unless you have to.
    retry=num-RnumRetry up to num times before aborting an I/O operation.
    -o ro-o roMount the file system for read-only access.
    -o rw-o rwMount the file system for read and write access.
    -R num-R numRetry the mount operation up to num times. If you have chosen soft mounting, fail I/O operations after num retries. The default value is 10.
    -r .size-r .sizeSet the read data block size to size bytes. size should be a power of 2 between 1024 and 32768. The default value is 8192. Use smaller block sizes for UDP mounts if you have frequent fragments dropped due to timeout messages on the client.
    soft-sIf operations on the file system time out, don't retry forever. Instead, give up after Retry timeouts. See option -R.
    -t num-t numTime out and retry an operation if it doesn't complete with in num 10 seconds. The default value is 10 (1 second).
    tcp-TUse TCP instead of UDP for mounts. This is more reliable, but slightly slower. In addition, not all implementations of NFS support TCP transport.
    -w .size- .sizeSet the write data block size to size bytes. size should be a power of 2 between 1024 and 32768. The default value is 8192. Use smaller block sizes for UDP mounts if you have frequent "fragments dropped due to timeout" messages on the server.

    Normally, the only options that are of interest are -o ro, if you specifically want to restrict write access to the file system, and soft, which you should always use.

    Purists claim that soft compromises data integrity, because it may leave data on the server machine in an unknown state. That's true enough, but in practice the alternative to soft mounting is to reboot the client machine. This is not only a nuisance, it also compromises data integrity. The only solution that doesn't always compromise data integrity is to wait for the server machine to come back online. It's unlikely that anybody will wait more than a few hours at the outside for a server to come back.

    A typical mount operation might be:

    # mount -o soft presto:/usr /presto/usr
    

    Where to mount NFS file systems

    You can mount an NFS file system just about anywhere you would mount a local file system. Still, a few considerations will make life easier. In this discussion, we'll assume that we have a large number of file systems mounted on freebie, and we want to make them accessible to presto.

  • If you have a "special" file system that you want to mount on multiple systems, it makes sense to mount it on the same mount point on every system. freebie has two file systems, /S and /src, which contain source files and are shared between all systems on the network. It makes sense to mount the file system on the same directory.
  • freebie has a CD-ROM changer, and mounts the disks on /cdrom/1 to /cdrom/7. presto finds that too confusing, and mounts one of them on /cdrom.
  • Some other file systems can't be mounted in the same place. For example, freebie:/usr can't be mounted on /usr. Mount them on directories that match the system name. For example, mount freebie:/usr on /freebie/usr.
  • After doing this, you might find the following file systems mounted on freebie:

    # df
    Filesystem   1024-blocks     Used   Avail  Capacity  Mounted on
    /dev/ad0s1a        30206    26830     960     97%    /
    /dev/ad0s1e      1152422  1016196   44034     96%    /usr
    /dev/da0h         931630   614047  243052     72%    /src
    /dev/dalh        2049812  1256636  629192     67%    /home
    procfs                 4        4       0    100%    /proc
    /dev/cd0a         656406   656406       0    100%    /cdrom/1
    /dev/cdla         664134   664134       0    100%    /cdrom/2
    /dev/cd2a         640564   640564       0    100%    /cdrom/3
    /dev/cd3a         660000   660000       0    100%    /cdrom/4
    /dev/cd4a         525000   525000       0    100%    /cdrom/5
    /dev/cd5a         615198   615198       0    100%    /cdrom/6
    /dev/cd6a         278506   278506       0    100%    /cdrom/7
    

    On presto, you might see:

    # df
    Filesystem    1024-blocks     Used    Avail  Capacity    Mounted on
    /dev/da0s1a         29727    20593     6756     75%      /
    /dev/da0s1e       1901185   742884  1006207     42%      /usr
    procfs                  4        4        0    100%      /proc
    freebie:/           30206    26830      960     97%      /freebie
    freebie:/usr      1152422  1016198    44032     96%      /freebie/usr
    freebie:/home     2049812  1256638   629190     67%      /home
    freebie:/src       931630   614047   243052     72%      /src
    freebie:/S        3866510  1437971  2119219     40%      /S
    freebie:/cdrom/1   656406   656406        0    100%      /cdrom
    

    Mounting NFS file systems automatically

    If you want to mount NFS files automatically at boot time, make an entry for them in the file /etc/fstab. You can even do this if you don't necessarily want to mount them: just add the keyword noauto, and mountall will ignore them at boot time. The advantage is that you then just need to specify, say,

    # mount /src
    

    instead of:

    # mount -s freebie:/src /src
    

    See the description of /etc/fstab on page 566 for more information.

    NFS strangenesses

    NFS mimics a local file system across the network. It does a pretty good job, but it's not perfect. Here are some things that you should consider.

    No devices

    NFS handles disk files and directories, but not devices. Actually, it handles devices too, but not the way you would expect.

    In a UNIX file system, a device is more correctly known as a device node: it's an inode that describes a device in terms of its major and minor numbers (see page 195). The device itself is implemented by the device driver. NFS exports device nodes in UFS file systems, but it doesn't interpret the fact that these devices are on another system. If you refer to the devices, one of three things will happen:

  • If a driver for the specified major number exists on your local system, and the devices are the same on both systems, you will access the local device. Depending on which device it is, this could create some subtle problems that could go undetected for quite awhile.
  • If a driver for the specified major number exists on your local system, and the devices are different on the two systems, you will still access the local device with the same major and minor numbers, if such a device exists. The results could be very confusing.
  • If no driver for the specified major number exists on your local system, the request will fail. This can still cause considerable confusion.
  • If the NFS server system runs devfs, the device nodes are not exported. You won't see anything unless there are left over device nodes from before the time of migration to devfs.

    Just one file system

    NFS exports file systems, not directory hierarchies. Consider the example on page 444. presto has mounted both freebie:/ and freebie:/usr. If it were just to mount freebie:/, we would see the directory /freebie/usr, but it would be empty.

    Things can get even stranger: you can mount a remote file system on a directory that is not empty. Consider the following scenario:

  • You install FreeBSD on system feebie. In single-user mode, before mounting the other file systems, you create a directory /usr/bin and a file /usr/bin/vi. Since the /usr file system isn't mounted, this file goes onto the root file system.
  • You go to multi-user mode and mount the other file systems, including the file system for /usr. You can no longer see the /usr/bin/vi you put there in single-user mode. It hasn't gone away, it's just masked.
  • On presto, you mount the file system freebie:/ on freebie. If you list the contents of the directory /freebie/usr, you will see the original file vi, and not the contents that the users on freebie will see.
  • Страницы:

    Finally we have set up the network connections, and everything is working. What can we do with the network? In this part of the book, we'll take a look at some of the more important services that make up the application layer.

    The Internet protocols perform most services with a pair of processes: a client at one end of the link that actively asks for services, and a server at the other end of the link that responds to requests and performs the requested activity. These terms are also used to describe computer systems, but here we're talking about processes, not systems. In this chapter, we'll look at the client side of things, and in Chapter 25, Basic network access: servers we'll look at the corresponding servers.

    Probably the single most important network service is the Hypertext Transfer Protocol or HTTP, the service that web browsers use to access the Web. We'll look at web browsers in the next section.

    The next most important service is probably the Simple Mail Transfer Protocol or SMTP, the primary service for sending mail round the Internet. There's also the Post Office Protocol or POP, which is used by systems unable to run SMTP. This topic is so important that we'll devote Chapters 26 and 27 to it.

    To use a remote machine effectively, you need better access than such specialized servers can give you. The most powerful access is obviously when you can execute a shell on the remote machine; that gives you effectively the same control over the machine as you have over your local machine. A number of services are available to do this. In the olden days, you would use telnet or rlogin to log into another machine. These programs are still with us, but security concerns make them effectively useless outside a trusted local network. We'll look at them briefy on page 430.

    The preferred replacement is ssh, which stands for secureshell. In fact, it's not a shell at all, it's a service to communicate with a remote shell. It encrypts the data sent over the network, thus making it more difficult for crackers to abuse. We'll look at it in detail on page 419.

    Another important service is the ability to move data from one system to another. There are a number of ways of doing this. The oldest programs are rcp and ftp. These programs have the same security concerns as telnet and rlogin, though ftp still has some uses. More modern copying programs use scp, which is based on ssh. We'll look at file copy programs on page 432. In addition, rsync is a useful program for maintaining identical copies files on different systems. We'll look at it on page 437.

    A some what different approach is the Network File System or NFS, which mounts file systems from another machine as if they were local. We look at NFS clients on page 441.

    The World Wide Web

    For the vast majority of the public, the Internet and the ) run FreeBSD. Even Microsoft runs FreeBSD on its Hotmail service (http://www.hotmail.com/), though they have frequently denied it, and for image reasons they are moving to their own software.

    Web browsers

    A web browser is a program that retrieves documents from the Web and displays them. The base FreeBSD system does not include a web browser, but a large number are available in the Ports Collection. All web browsers seem to have one thing in common: they are buggy. They frequently crash when presented with web pages designed for Microsoft, and in other cases they don't display the page correctly. In many cases this is due to poorly designed web pages, of course.

    Currently, the most important web browsers are:

  • netscape was once the only game in town, but it's now showing its age. In addition, many web sites only test their software with Microsoft, and their bugs cause problems with netscape.
  • mozilla is derived from the same sources as netscape, but comes in source form. It has now reached the stage where it is less buggy than netscape. A number of other browsers, such as galeon and skipstone, are based on mozilla. They're all available in the Ports Collection. galeon is included in the instant-workstation port described in Chapter 6.
  • konqueror is included with the KDE port.
  • Opera is a new browser that some people like. The version in the Ports Collection is free, but it makes up for it by giving you even more advertisements than the web pages give you anyway. You can buy a version that doesn't display the advertisements.
  • lynx is a web browser for people who don't use X. It displays text only.
  • You may note two omissions from this list. Microsoft's Internet Explorer is not available for FreeBSD. Not many people have missed it. Also, mosaic, the original web browser, is now completely obsolete, and it has been removed from the Ports Collection.

    In addition to these browsers, StarOffice and OpenOffice include integrated browsers. You may find you prefer them.

    This book does not deal with how to use a web browser: just about everybody knows how to use one. You can also get help from just about any browser; just click on the text or icon marked Help or ?.

    ssh

    ssh is a secure shell, a means of executing programs remotely using encrypted data transfers. There are a number of different implementations of ssh: there are two different protocols, and the implementations are complicated both by bugs and license conditions. FreeBSD comes with an implementation of ssh called OpenSSH, originally developed as part of the OpenBSD project.

    Using ssh is simple:

    $ ssh freebie
    The authenticity of host 'freebie.example.org (223.147.37.1)' can't be established.
    DSA key fingerprint is 08:f7:c4:14:48:0b:14:06:0e:2c:93:4b:1f:f6:ce:b5.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added 'freebie.example.org' (DSA) to the list of known hosts.
    grog@freebie.example.org's password:    as usual, doesn't echo
    Last login: Mon May 13 14:21:11 2002
    Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
    The Regents of the University of California. All rights reserved.
    FreeBSD 5.0-RELEASE (FREEBIE) #3: Sun Jan 5 13:25:02 CST 2003
    
    Welcome to FreeBSD!
    $ tty
    /dev/ttyp3
    $
    

    Once you get this far, you are connected to the machine in almost the same manner as if you were directly connected. This is particularly true if you are running X. As the output of the tty command shows, your "terminal" is a pseudo-tty or pty (pronounced "pity"). This is the same interface that you have with an xterm.

    It's worth looking in more detail at how the connection is established:

  • The first line (The authenticity...) appears once ssh has established preliminary contact with the remote system. It indicates that you're connected, but that the local system has no information about the remote system. Theoretically you could be connected to a different machine masquerading as the machine you want to connect to. ssh saves the fingerprint in ~/.ssh/known_hosts and checks it every time you connect to that machine thereafter.
  • The reference to DSA keys indicates that ssh is using the ssh Version 2 protocol. We'll look at the differences between the protocols below.
  • The password prompt is for the same password as you would see locally. The slightly different format is to clarify exactly which password you should enter. Again, a number of exploits are possible where you might find yourself giving away a password to an intruder, so this caution is justified.
  • When you log in via ssh, there's a chance that your TERM environment variable is set incorrectly. See table 7.3 on page 130 for more details. Remember that TERM describes the display at your end of the link. There is no display at the other end, but the other end needs to know the termcap parameters for your display. If you're running an xterm, this shouldn't be a problem: the name xterm propagates to the other end. If you're using a character-oriented display (/dev/ttyvx), however, your TERM variable is probably set to cons25, which many systems don't know. If systems refuse to start full-screen modes when you connect from a virtual terminal, try setting the TERM variable to ansi.

    To exit ssh, just log out. If you run into problems, however, like a hung network, you can also hit the combination Enter ~. Enter, which always drops the connection.

    Access without a password

    Sending passwords across the Net, even if they're encrypted, is not a complete guarantee that nobody else can get in: there are a number of brute-force ways to crack an encrypted password. To address this issue, ssh has an access method that doesn't require passwords: instead it uses a technique called public key cryptography. You have two keys, one of which you can give away freely, and the other of which you guard carefully. You can encrypt or decrypt with either key: data encrypted with the public key can be decrypted with the private key, and data encrypted with the private key can be decrypted with the public key.

    Once you have these keys in place, you can use the challenge-response method for authentication. To initiate an ssh connection, ssh sends your public key to the sshd process on the remote system. The remote system must already have a copy of this key. It uses it to encrypt a random text, a challenge, which it sends back to your system. The ssh process on your system decrypts it with your private key, which is not stored anywhere else, and sends the decrypted key back to the remote sshd. Only your system can decode the challenge, so this is evidence to the remote sshd that it's really you.

    By default, the private key for Version 1 of the protocol is stored in the file ~/.ssh/identity, and the public key is stored in the file ~/.ssh/identity_pub. For Version 2, you have a choice of two different encryption schemes, DSA and RSA. The corresponding private and public keys are stored in the files ~/.ssh/id_dsa, ~/.ssh/id_dsa.pub, ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub respectively. If you have the choice between DSA key sand RSA keys for protocol Version 2, use DSA keys, which are considered somewhat more secure. You still should have an RSA key pair in case you want to connect to a system that doesn't support DSA keys.

    There's still an issue of unauthorized local access, of course. To ensure that somebody doesn't compromise one system and then use it to compromise others, you need a kind of password for your private keys. To a void confusion, ssh refers to it as a passphrase. If ssh finds keys in the ~/.ssh directory, it attempts to use them:

    $ ssh hub
    Enter passphrase for key '/home/grog/.ssh/id_rsa':    (no echo)
    Last login: Sat Jul 13 17:27:33 2002 from wantadilla.lemis
    Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
         The Regents of the University of California. All rights reserved.
    FreeBSD 5.0-STABLE (HUB) #7: Thu Jun 26 12:44:34 PDT 2003
    (etc)
    

    Creating and distributing keys

    You create keys with the program ssh-keygen. Here's an example of generating all three keys:

    $ ssh-keygen -t rsa1
    Generating public/private rsa1 key pair.
    Enter file in which to save the key (/home/grog/.ssh/identity):  (ENTER pressed)
    Enter passphrase (empty for no passphrase):                      (no echo)
    Enter same passphrase again:                                     (no echo)
    Your identification has been saved in /home/grog/.ssh/identity.
    Your public key has been saved in /home/grog/.ssh/identity.pub.
    The key fingerprint is:
    02:20:1d:50:78:c5:7c:56:7b:1d:e3:54:02:2c:99:76 grog@bumble.example.org
    $ ssh-keygen -t rsa
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/grog/.ssh/id_rsa):    (ENTER pressed)
    Enter passphrase (empty for no passphrase):                      (no echo)
    Enter same passphrase again:                                     (no echo)
    Your identification has been saved in /home/grog/.ssh/id_rsa.
    Your public key has been saved in /home/grog/.ssh/id_rsa.pub.
    The key fingerprint is:
    95:d5:01:ca:90:04:7d:84:f6:00:32:7a:ea:a6:57:2d grog@bumble.example.org
    $ ssh-keygen -t dsa
    Generating public/private dsa key pair.
    Enter file in which to save the key (/home/grog/.ssh/id_dsa):    (ENTER pressed)
    Enter passphrase (empty for no passphrase):                      (no echo)
    Enter same passphrase again:                                     (no echo)
    Your identification has been saved in /home/grog/.ssh/id_dsa.
    Your public key has been saved in /home/grog/.ssh/id_dsa.pub.
    The key fingerprint is:
    53:53:af:22:87:07:10:e4:5a:2c:21:31:ec:29:1c:5f grog@bumble.example.org
    

    Before you can use these keys, you need to get the public keys on the remote site in the file ~/.ssh/authorized_keys. Older versions of ssh used a second file, ~/.ssh/authorized_keys2, for protocol Version 2, but modern versions store all the keys in the one file ~/.ssh/authorized_keys. There are a number of ways to get the keys in these files. If you already have access to the machine (via password-based authentication, for example), you can put them there yourself. Typically, though, you'll have to get somebody else involved. To make it easier, the public keys are in ASCII, so you can send them by mail. The three public keys generated above look like this:

    10243511012428427427480334544982386682254123065784505204062211656732932064601995
    56751223553035331118710873315456577313425763305854786629592671460454493321979564
    51897683927631476817528590966739503979593649232357835172621038275643667609041147
    5643317216 92291413130012157442638303275673247163400686283060339457790686649
     grog@bumble.example.org
    ssh-dss AAflAB3NzaC1kc3MaflACEAIltWeRXnqD9HqpLn5kugPSWHicJiu1r0I9dHg8F5m2EpmupyR
    YSmDzscAcsxifo50+1yXk3Vf4P1+EDsAwkyqFlujuMVeKoTYcOi1yrnLDWIDiAeIzt1BQ6ON^XqxwWKC
    q1eo1tXxOrTxw84VboHUuq4XFdt+yPJs8QdxLhj+jAAAAFQC1JL+tU19+UR+c45JGom6ae29d7wAAAIA
    vNgdN6rTitMjDCglN7Rq3/8WgI1kzh20XURbCe1n2yYsFifcImKb0sUYD2qsB5++gogzsse2IxyIECRC
    uyCOOFXIQ7WqkvjTp/T+fuwGPIlho8eeNDRKKABUhHjkuApnoYLIC1O5uyciJ+dIbGaRtGFJr0da7Klk
    jOLkiv3sR1gAAAIAwgKfWsRSQJyRZTkKGIHxn3EWTVSicnIRYza+HTaMuMFHMTkNMZBjhei6EoCFpV9B
    1QB9MlIZgf6WXM2DlmtdUbpm7KFA669/LZT2LvxbtGP/B++7s0PMs0AgKrKgUxnhVweufMZlPvPPPOz4
    QS1ZZ5kYhN+lu0S8yuioXYNlDtA== grog@bumble.example.org
    ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA1/W3oa1ZEs58KRWMzsrZWMXzPfwoqQ+Z59p6SJlzhevs
    XG1PAVWra2wcRz1utKFBjkDpJfEe+09L7h8VAx1aYCHji50tKI8F8YT8PuWGH+UqF/37Wl292SsXsb8g
    80yyymSfxgOM/HegvOuHQu46MfaPj9ddfcgY06z3ufcmXts= grog@bumble.example.org
    

    In the original, each key is on a single line.

    Obviously you don't want anybody messing with your authorized keys files, so ssh requires that the files belong to you and are only writeable by you. These two files typically contain multiple keys; to add a new one, just append it to the end of the file. For example, if you receive a newkey and store it in the file newkey, copy it like this:

    $ cat newkey >> ~/.ssh/authorized_keys
    

    Authenticating automatically

    Having to supply the passphrase can become a nuisance and even a serious problem. If you want to run ssh from scripts, it may not even be possible to supply the passphrase. ssh has another feature available here: it has an authentication agent that keeps track of the keys.

    The authentication agent is called ssh-agent, and you add keys with ssh-add. Due to the manner in which it is started, ssh-agent needs to be the ancestor of the shell you are running, and of the ssh-add command. Otherwise you see error messages like this:

    $ ssh-agent
    SSH_AUTH_SOCK=/tmp/ssh-cwT9aBbV/agent.42902; export SSH_AUTH_SOCK;
    SSH_AGENT_PID=42903; export SSH_AGENT_PID;
    echo Agent pid 42903;
    $ ssh-add
    Could not open a connection to your authentication agent.
    

    To solve this problem, execute the agent in your current environment with eval, then run ssh-add:

    $ eval ‘ssh-agent’
    $ ssh-add
    Enter passphrase for /home/grog/.ssh/id_rsa: (enterthepassphrase)
    Identity added: /home/grog/.ssh/id_rsa (/home/grog/.ssh/id_rsa)
    Identity added: /home/grog/.ssh/id_dsa (/home/grog/.ssh/id_dsa)
    Identity added: /home/grog/.ssh/identity (grog@zaphod.example.org)
    

    You can use ssh-add's -l flag to list which keys the authentication agent currently knows about:

    $ ssh-add -l
    1024 02:20:1d:50:78:c5:7c:56:7b:1d:e3:54:02:2c:99:76 grog@zaphod.example.org (RSA1)
    1024 95:d5:01:ca:90:04:7d:84:f6:00:32:7a:ea:a6:57:2d /home/grog/.ssh/id_rsa (RSA)
    1024 53:53:af:22:87:07:10:e4:5a:2c:21:31:ec:29:1c:5f /home/grog/.ssh/id_dsa (DSA)
    

    If you're using a Bourne-style shell such as bash, you can automate a lot of this by putting the following commands in your .bashrc or .profile file:

    if tty >/dev/null; then
      ssh-add -l > /dev/null
      if [ $? -ne 0 ]; then
        eval 'ssh-agent’
      fi
    fi
    

    This first uses the tty command to check if this is an interactive shell, then checks if you already have an authentication agent. If it doesn't, it starts one. Don't start a new authentication agent if you already have one: you'd lose any keys that the agent already knows. This script doesn't add keys, because this requires your intervention and could be annoying if you had to do it every time you start a shell.

    Setting up X to use ssh

    If you work with X, you have the opportunity to start a large number of concurrent ssh sessions. It would be annoying to have to enter keys for each session, so there's an alternative method: start X with an ssh-agent, and it will pass the information on to any xterms that it starts. Add the following commands to your .xinitrc:

    eval 'ssh-agent’
    ssh-add < /dev/null
    

    When you run ssh-add in this manner, without an input file, it runs a program to prompt for the passphrase. By default it's /usr/X11R6/bin/ssh-askpass, but you can change it by setting the SSH_ASKPASS environment variable. /usr/X11R6/bin/ssh-askpass opens a window and prompts for a passphrase. From then on, anything started under the X session will automatically inherit the keys.

    ssh tunnels

    Tunneling is a technique for encapsulating an IP connection inside another IP connection. Why would you want to do that? One reason is to add encryption to an otherwise unencrypted connection, such as telnet or POP. Another is to get access to a service on a system that does not generally supply this service to the Internet.

    Let's consider using might have the following parameters:

    (рис 24.1)

    But what if the server is firewalled from the global Internet, so you can't access it directly? That's when you need the ssh tunnel. The ssh tunnel creates a local connection at each end and a separate secure connection across the Internet:

    (рис 24.2)

    The ssh connection is shown in fixed italic font. It looks just like any other ssh connection. The differences are the local connections at each end: instead of talking to presto port 80 (http), you talk to port 4096 on your local machine. Why 4096? It's your choice; you can use any port above 1024. If you're on andante, you can set up this tunnel with the command:

    $ ssh -L 4096:presto.example.org:80 presto.example.org
    

    To do the same thing from the presto end, you'd set up a reverse tunnel with the –R option:

    $ ssh -R 4096:presto.example.org:80 andante.example.org
    

    These commands both set up a tunnel from port 4096 on . You still need to supply the name of the system to connect to; it doesn't have to be the same. For example, you might not be able to log in to the web server, but you could access your machine back home, and it has access to the web server. In this case, you could connect to your machine at home:

    $ ssh -L 4096:presto.example.org:80 freebie.example.org
    

    In addition to setting up the tunnel, ssh can create a normal interactive session. If you don't want this, use the -f option to tell ssh to go into the background after authentication. You can also specify a command to execute, but this is no longer necessary for protocol version 2. If you don't want to execute a command, use the -N option:

    $ ssh -L 4096:presto.example.org:80 presto.example.org -f –N
    

    If you're running protocol version 1, you can use sleep with an appropriately long timeout, in this example 1 hour:

    $ ssh -L 4096:presto.example.org:80 presto.example.org -f sleep 3600
    

    Tunneling X

    Running X clients on the remote machine is special enough that ssh provides a special form of tunneling to deal with it. To use it, you must tell ssh the location of an .Xauthority file. Do this by adding the following line to the file ~/.ssh/environment:

    XAUTHORITY=/home/yourname /.Xauthority
    

    The name must be in fully qualified form: ssh does not understand the shortcut ~/ to represent your home directory. You don't need to create ~/.Xauthority, though: ssh can do that for you.

    Once you have this in place, you can set up X tunneling in two different ways. To start it from the command line, enter something like:

    $ ssh -X -f website xterm
    

    As before, the -f option tells ssh to go into the background. The -X option specifies X tunneling, and ssh runs an xterm on the local machine. The DISPLAY environment variable points to the (remote) local host:

    $ echo $DISPLAY
    localhost:13.1
    

    Other uses of tunnels

    Tunneling has many other uses. Another interesting one is bridging networks. For example, http://unix.za.net/gateway/documentation/networking/vpn/fbsd.html describes how to set up a VPN (Virtual Private Network) using User PPP and an ssh tunnel.

    Configuring ssh

    It can be a bit of a nuisance to have to supply all these parameters to ssh, but you don't have to: you can supply information for frequently accessed hosts in a configuration file. On startup, ssh checks for configuration information in a number of places. It checks for them first in the command line options, then in you configuration file ~/.ssh/config, and finally in the system-wide configuration file /etc/ssh/ssh_config. The way it treats duplicate information is pretty much the opposite of what you'd expect: unlike most other programs, options found in a configuration file read in later do not replace the options found in an earlier file. Options on the command line replace those given in configuration files.

    In practice, such conflicts happen less often than you might expect. The file /etc/ssh/ssh_config, the main configuration file for the system, normally contains only comments, and by default you don't even get a local ~/.ssh/config.

    sshconfig can contain a large number of options. They're all described in the man page ssh_config(8) ,but it's worth looking at some of the more common ones. In this section we'll look at some of the more common configuration options.

  • The entry Host is special: the options that follow, up to the end of the file or the next following Host argument, relate only to hosts that match the arguments on the Host line.
  • Optionally, ssh can compress the data streams. This can save a lot of traffic, but it can also increase CPU usage, so by default it is disabled. You can do this by passing the -C flag to ssh, but you can also do so by setting Compression yes in the configuration file.
  • You can escape out of an ssh session to issue commands to ssh with the EscapeChar. By default it's the tilde character, ~ Other programs, notably rlogin, use this character as well, so you may want to change it. You can set this value from the ssh command line with the -e option.
  • To forward an X11 connection, as shown above, you can also set the ForwardX11 variable to yes. This may be useful if you frequently access a remote machine and require X forwarding. This also sets the DISPLAY environment variable correctly to go over the secure channel.
  • By default, ssh sends regular messages to the remote sshd server to check if the remote system has gone down. This can cause connections to be dropped on a flaky connection. Set the KeepAlive option to no to disable this behavior.
  • Use the LocalForward parameter to set up a tunnel. The syntax is similar to that of the -L option above: on andante, instead of the command line:
    $ ssh -L 4096:presto.example.org:80 presto.example.org
    

    You would put the following in your ~/.ssh/config:

    host presto.example.org
    LocalForward 4096 presto.exanple.org:80
    

    Note that the first port is separated from the other two parameters by a space, not a colon.

  • Similarly, you can set up a reverse tunnel with the RemoteForwar parameter. On presto, instead of the command line:
    $ ssh -R 4096:presto.example.org:80 andante.example.org
    

    you would put the following in your ~/.ssh/config:

    host andante.example.org
    RemoteForward 4096 presto.example.org:80
    
  • By default, ssh uses password authentication if it can't negotiate a key pair. Set PasswordAuthentication to no if you don't want this.
  • Normally ssh connects to the server on port 22 (ssh). If the remote server uses a different port, specify it with the Port keyword. You can also use the -p option on the ssh command line.
  • By default, ssh attempts to connect using protocol 2, and if that doesn't work, it tries to connect using protocol 1. You can override this default with the Protocol keyword. For example, to reverse the default and try first protocol 1, then protocol 2, you would write:
    Protocol 1,2
    
  • By default, ssh refuses to connect to a known host if its key fingerprint changes. Instead, you must manually remove the entry for the system from the ~/.ssh/known_hosts or ~/.ssh/known_hosts2 file. This can indicate that somebody is faking the remote machine, but more often it's because the remote machine has really changed its host key, which it might do at every reboot. If this gets on your nerves, you can add this line to your configuration file:
    StrictHostKeyChecking no
    

    This doesn't stop the warnings, but ssh continues:

    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    @    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!    @
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
    Someone could be eavesdropping on you right now (man-in-the-middle attack)!
    It is also possible that the DSA host key has just been changed.
    The fingerprint for the DSA key sent by the remote host is
    95:80:4c:fb:cc:96:1b:36:c5:c9:2b:cb:d1:d4:16:68.
    Please contact your system administrator.
    Add correct host key in /home/grog/.ssh/known_hosts2 to get rid of this message.
    Offending key in /home/grog/.ssh/known_hosts2:39
    
  • ssh assumes that your user name on the remote system is the same as the name on the local system. If that's not the case, you can use the User keyword to specify the remote user name. Alternatively, you can use the format:
    $ ssh newuser@remotehost.org
    
  • Summary of files in ~/.ssh

    In addition to the files we have discussed, you will find two other files in the ~/.ssh directory:

  • known hosts contains the key fingerprints of all hosts to which you have connected. The example on page 419 shows how ssh adds a key.
  • randomseed is a seed used to generate the keys.
  • In summary, then, you can expect the following files in your ~/.ssh:

    drwx------  2  grog  grog   512  Jan  18  21:04  .                 directory
    -rw-r--r--  1  grog  grog  1705  Oct  26   1999  authorized keys   keys
    -rw-r--r--  1  grog  grog   844  Jan  27  22:18  authorized keys2  keys, Version 2 only
    -rw-r--r--  1  grog  grog    25  Oct  20  01:35  environment       environment for sshd
    -rw-------  1  grog  grog   736  Jul  19  15:40  id dsa            DSA private key
    -rw-r--r--  1  grog  grog   611  Jul  19  15:40  id dsa.pub        DSA public key
    -rw-------  1  grog  grog   951  Jul  19  15:40  id rsa            RSA private key
    -rw-r--r--  1  grog  grog   231  Jul  19  15:40  id rsa.pub        RSA public key
    -rw-------  1  grog  grog   536  Jul  19  15:39  identity          RSA1 private key
    -rw-r--r--  1  grog  grog   340  Jul  19  15:39  identity.pub      RSA1 public key
    -rw-------  1  grog  grog  1000  Jul  25   1999  known hosts       list of known hosts
    -rw-------  1  grog  grog   512  Jul  25   1999  random seed       for key generation
    

    Note particularly the permissions and the ownership of the files and the directory itself. If they are wrong, ssh won't work, and it won't tell you why not. In particular, the directory must not be group writeable.

    Troubleshooting ssh connections

    A surprising number of things can go wrong with setting up ssh connections. Here are some of the more common ones:

  • After some delay, you get the message:
    ssh: connect to address 223.147.37.76 port 22: Operation timed out
    

    This probably means that the remote host is down, or that you can't reach it due to network problems.

  • You get the message:
    ssh: connect to address 223.147.37.65 port 22: Connection refused
    
    This means that the remote host is up, but no sshd is running.
  • You have set up keys, but you still get a message asking for a password.

    This can mean a number of things: your ssh-agent isn't running, you haven't added the keys, the other end can't find them, or the security on the keys at the other end is incorrect. You can check the first two like this:

    $ ssh-add -l
    Could not open a connection to your authentication agent.
    

    This message means that you haven't run ssh-agent. Do it like this:

    $ eval ‘sh-agent’
    Agent pid 95180
    $ ssh-add -l
    The agent has no identities.
    $ ssh-add
    Enter passphrase for /home/grog/.ssh/id_rsa:    no echo
    Identity added: /home/grog/.ssh/id_rsa (/home/grog/.ssh/id_rsa)
    Identity added: /home/grog/.ssh/id_dsa (/home/grog/.ssh/id_dsa)
    Identity added: /home/grog/.ssh/identity (grog@freebie.lemis.com)
    $ ssh-add -l
    1024 02:20:1d:50:78:c5:7c:56:7b:1d:e3:54:02:2c:99:76 grog@zaphod.example.org (RSA1)
    1024 95:d5:01:ca:90:04:7d:84:f6:00:32:7a:ea:a6:57:2d /home/grog/.ssh/id_rsa (RSA)
    1024 53:53:af:22:87:07:10:e4:5a:2c:21:31:ec:29:1c:5f /home/grog/.ssh/id_dsa (DSA)
    

    In this case, all three keys are set correctly. If you have, say, only an RSA1 (protocol Version 1) key, and the other end doesn't support protocol Version 1, ssh will ask for a password.

  • You get a message like this:
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    @    WARNING: REMDTE HOST IDENTIFICATION HAS CHANGED!    @
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
    Someone could be eavesdropping on you right now (man-in-the-middle attack)!
    It is also possible that the DSA host key has just been changed.
    The fingerprint for the DSA key sent by the remote host is
    95:80:4c:fb:cc:96:1b:36:c5:c9:2b:cb:d1:d4:16:68.
    Please contact your system administrator.
    Add correct host key in /home/grog/.ssh/known_hosts2 to get rid of this message.
    Offending key in /home/grog/.ssh/known_hosts2:39
    

    There are two possible reasons for this message. As the message states, one is that somebody is trying to intercept the connection, and the other one is that the remote system has changed its host key. The latter is by far the more common. To fix this problem, you have two choices:

  • Edit your ~/.ssh/known_hosts2 file and remove references to the remote system. The message suggests changing line 39, but you might have more than one key for this system in this file. If one is wrong, there's a good chance that any others will be too, so you should remove all references.
  • Add the following line to your ~/.ssh/config file:
    StrictHostKeyChecking no
    

    It doesn't remove the warning, but it allows you to connect anyway.

  • ssh includes debugging options that may help debug problems setting up connections. Use the -v option, up to three times, to get ssh to display largely undocumented information about what is going on. The output is pretty verbose; with three -v options you get nearly 200 lines of information.

    telnet

    As mentioned above, telnet is an older, unencrypted program that connects to a shell on a remote system. You might find it of use when connecting to a system that doesn't have ssh. Be very careful not to use valuable passwords, since they are transmitted in the clear. Apart from that, you use it pretty much in the same way as ssh:

    $ telnet freebie
    Trying 223.147.37.1...
    Connected to freebie.example.org.
    Escape character is '^]'.
    login: grog
    Password:    (no echo)
    
    FreeBSD/i386 (wantadilla.example.org) (ttypj)
    Last login: Mon Oct 14 17:51:57 from sydney.example.org
    Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
        The Regents of the University of California.  All rights reserved.
    
    FreeBSD 5.0-RELEASE (FREEBIE) #0: Tue Dec 31 19:08:24 CST 2002
    
    You have new mail.
    If I have seen farther than others, it is because I was standing on the
    shoulders of giants.
      -- Isaac Newton
    
    In the sciences, we are now uniquely privileged to sit side by side
    with the giants on whose shoulders we stand.
      -- Gerald Holton
    
    If I have not seen as far as others, it is because giants were standing
    on my shoulders.
      -- Hal Abelson
    
    In computer science, we stand on each other's feet.
      -- Brian K. Reid
    $ tty
    /dev/ttyp9
    $
    

    Once you get this far, you are connected to the machine in an almost identical manner as if you were directly connected. This is particularly true if you are running X. As the output of the tty command shows, your "terminal" is a pseudo-tty or pty (pronounced "pity"). This is the same interface that you will have with an xterm.

    It's worth looking in more detail at how the connection is established:

  • The first line (Trying...)appears as soon as telnet has resolved the IP address.
  • The next three lines appear as soon as it has a reply from the other end. At this point, there can be a marked delay before telnet continues. telnet performs a reverse DNS lookup to find the name of your system. If you get a delay here, it could be an indication that your reverse lookup is not working correctly. After DNS times out, it will continue normally, but the delay is a nuisance.
  • Logging in is almost exactly the same as logging in locally. Normally you won't be able to log in directly as root, unless you have set /dev/ptyx as secure in your /etc/ttys (see page 197 for further details). It's not a good idea to set your ptys as secure. Use su instead if you want to become root.
  • When you log in via telnet, there's a good chance that your TERM environment variable will be set incorrectly. See Table 7-3 on page 130 for more details. TERM describes the display at your end of the display, not the other end. If you're running an xterm, this shouldn't be a problem: probably the name xterm will propagate to the other end. If you're using a character-oriented display (/dev/ttyvx), however, your TERM variable will probably be set to cons25, which many systcodes don't know. If the rcodeote systcode refuses to start programs in full-screen modes, try setting the TERM variable to ansi.

    To exit telnet, you just log off. If you run into problems, however, like a hung network, you can also hit Ctrl-] to enter telnet command mode, and from there enter quit:

    $ ^]
    telnet> quit
    $
    

    If you hit Ctrl-] by accident, just hit Enter to return to the telnet session.

    Secure telnet

    Recent releases of FreeBSD telnet include a secure connection option. You can recognize it by the different messages that appear when you connect:

    $ telnet freebie
    Trying 223.147.37.1...
    Connected to freebie.example.org.
    Escape character is '^]'.
    Trying SRA secure login:
    User (grog):
    Password:
    [SRA accepts you ]
    

    There's no particular reason to use this version of telnet; it's non-standard, and you're still better off with ssh.

    Using telnet for other services

    The way we have used telnet so far, it connects to the default port, telnet (number 23, as you can see in the file /etc/services). This isn't the only possibility, though: you can tell telnet which port to connect to. In Chapter 27, Electronic mail: servers, we'll see how to communicate with sendmail using telnet on port smtp page 502, and how to communicate with POP on port pop, page 504. There are many other such uses.

    Copying files

    The other basic function involves copying files between systems. The traditional tools are ftp and rcp. Neither use encryption, so it's preferable to use scp, a variant of ssh. Nevertheless, ftp has its uses. About the only use for rcp is on systems that don't support scp, or systems where security is not an issue, and scp is so slow that it's not practical. The good news: you use rcp in pretty much the same manner as scp: scp was designed to be compatible with rcp, so you don't need to learn anything else if you want to use it.

    scp

    scp is a variant of ssh used for remote copying. The same access considerations apply as for ssh. The syntax for copying is similar to the syntax used by NFS: to copy a file /var/log/messages from presto to the file prestomessages on the local machine, you might enter:

    $ scp presto:/var/log/messages prestomessages
    

    As with ssh, if you need to authenticate as a different user, you can use the form user@system.scp does not support the -l option to specify the user name.

    scp has a number of options reminiscent of cp:

  • • Use the -p option to preserve modification times and permissions where possible. Note that this means you can't use ssh's -p option to specify an alternative port. scp uses the -P option for this instead.
  • • Use the -r option to recursively copy directories. You don't have to supply full path names to scp; you can write things like:
  • $ scp remotehost:file .
    

    This looks for a file called file in your home directory on the remote machine and copies it to your current local directory. Note the difference: there is no way for scp to know a different remote directory, so relative paths are always relative to the home directory on that machine.

    ftp

    ftp is the Internet File Transfer Program, and is the standard way to transfer large files long distances across the Net. It works for small files and short distances too, but you may find that scp or NFS are better alternatives in these areas.

    One serious drawback in duplicating files across the net is that you need to have permission to access the remote system. Traditionally, you need a user ID to access a system. Of course, the file server could have a specific user ID without a password, but that would throw the system open to attack from crackers. ftp solves this problem by recognizing the special user ftp. This user name used to be anonymous, but it turned out to be a problem to spell. ftp servers still accept the name anonymous as well. Login is special: you don't need a password, but by convention, to help the system administrators with their bookkeeping, you should enter your real user ID in place of the password when logging in as ftp.A typical session might look like:

    $ ftp ftp.freebsd.org
    Connected to ftp.beastie.tdk.net.
    cd 220 ftp.beastie.tdk.net FTP server (Version 6.00LS) ready.
    331 Guest login ok, send ident as password.
    Password:    password does not echo
    230 Guest login ok, access restrictions apply.
    Remote system type is UNIX.
    Using binary mode to transfer files.
    ftp> bin    to ensurebinary transfer
    200 Type set to I.
    230- The FreeBSD mirror at Tele Danmark Internet.
    Moremessagesomitted Name (grog): ftp
    331 Guest login ok, send your email address as password.
    ftp> cd /pub/FreeBSD/ports/distfiles
    250 CWD command successful.
    ftp> get xtset-1.Ctar.gz
    local: xtset-1.0.tar.gz remote: xtset-1.0.tar.gz
    229 Entering Extended Passive Mode (|||58059|)
    150 Opening BINARY mode data connection for 'xtset-1.0.tar.gz'   (4239 bytes).
    100%  |*************************************|    4239    5.49 KB/s  00:00
    226 Transfer complete.
    4239 bytes received in 00:00 (5.49 KB/s)
    ftp> ^D
    221 Goodbye.
    

    There are a number of things to note about this transfer:

  • The server may have multiple names, and the one you use may not be its canonical name (the name specified in the server's DNS A record—see page 363). By convention, the first part of the name of an , but the canonical name of the server is ftp://ftp.beastie.tdk.net.
  • Some versions of ftp transmit in ASCII mode by default: they change every incidence of the ASCII line feed character (the C language constant \n) to the sequence \r\n (they prep end an ASCII carriage return character). This permits you to print the results on normal printers, but makes a terrible mess of binary files. Transmitting in binary form always works. As the message shows, the FreeBSD ftp server uses binary mode, but it doesn't harm to enter the bin command. The message Type set to I. is ftp's way of telling you that it has set binary transmission mode.
  • The line of **** is an indication of the progress of the transfer. It's specific to BSD; other ftp clients don't show you anything here.
  • Specifying file names as URIs

    This transmission is fairly typical, and it's the traditional way to do it. FreeBSD has another method, though, which can be of use: instead of the interactive approach, you can specify the file name as a URI, and you can use ftp to download HTTP documents from a web server. For example, the last transfer can be simplified to:

    $ ftp ftp://ftp.freebsd.org/pub/FreeBSD/ports/distfiles/xtset-l.O.tar.gz
    Connected to ftp.beastie.tdk.net.
    220 ftp.beastie.tdk.net FTP server (Version 6.00LS) ready.
    331 Guest login ok, send your email address as password.
    ...
    230 Guest login ok, access restrictions apply.
    Remote system type is UNIX.
    Using binary mode to transfer files.
    200 Type set to I.
    250 CWD command successful.
    250 CWD command successful.
    250 CWD command successful.
    250 CWD command successful.
    local: xtset-1.0.tar.gz remote: xtset-1.0.tar.gz
    229 Entering Extended Passive Mode (|||59779|)
    150 Opening BINARY mode data connection for 'xtset-1.0.tar.gz' (4239 bytes).
    100%  |*************************************|  4239  5.82 KB/s  00:00
    226 Transfer complete.
    4239 bytes received in 00:00 (5.81 KB/s)
    Goodbye.
    

    Note that this method implies anonymous ftp: you don't have to log in. In the same way, you can download a web page like this:

    $ ftp http://www.FreeBSD.org/index.litml
    Requesting http://www.FreeBSD.org/index.html
    100%  |*************************************| 26493  12.20 KB/s 00:02
    26493 bytes retrieved in 00:02 (12.17 KB/s)
    

    Note that in this case you can't just specify the URI as http://www.FreeBSD.org: you must specify the real file name.

    Other ftp commands

    ftp has about sixty commands, some of which can be of use. We'll look at the most useful commands in the following sections.

    mget

    ftp> ls
    200 PORT command successful.
    150 Opening ASCII mode data connection for /bin/ls.
    -rw-rw-r--  1  117  1001    43367  Nov   1  02:37  gcc-2.5.0-2.5.2.diff.gz
    -rw-rw-r--  1  117  1001     1010  Nov   1  02:37  gcc-2.5.1-2.5.2.diff.gz
    -rw-rw-r--  1  117  1001    78731  Nov  11  13:53  gcc-2.5.2-2.5.3.diff.gz
    -rw-rw-r--  1  117  1001    13931  Nov  17  09:27  gcc-2.5.3-2.5.4.diff.gz
    -rw-rw-r--  1  117  1001    76271  Nov  27  16:48  gcc-2.5.4-2.5.5.diff.gz
    -rw-rw-r--  1  117  1001     8047  Dec   3  09:22  gcc-2.5.5-2.5.6.diff.gz
    -rw-rw-r--  1  117  1001  5994481  Nov  27  16:49  gcc-2.5.5.tar.gz
    -rw-rw-r--  1  117  1001    10753  Dec  12  19:15  gcc-2.5.6-2.5.7.diff.gz
    -rw-rw-r--  1  117  1001    14726  Jan  24  09:02  gcc-2.5.7-2.5.8.diff.gz
    -rw-rw-r--  1  117  1001  5955006  Dec  22  14:16  gcc-2.5.7.tar.gz
    -rw-rw-r--  1  117  1001  5997896  Jan  24  09:03  gcc-2.5.8.tar.gz
    226 Transfer  complete.          
    ftp>
    

    Frequently you need to copy more than a single file. For example, if you currently have gcc-2.5.0 and want to get gcc-2.5.8, you will discover the following files on the file server:

    In other words, you have the choice of transferring 6 MB of software in gcc-2.5.8.tar.gz or seven incremental patch files with a total of less than 250 kB. On the other hand, copying the diffs requires typing all these long, complicated file names, so you might decide it's easier just to duplicate the whole 6 MB.

    There is an easier way: mget (multiple get) duplicates files matching a wild card. You could perform the complete transfer with:

    ftp> mget gcc-2*diff.gz
    mget gcc-2.5.0-2.5.2.diff.gz?y
    200 PORT command successful.
    150 Opening BINARY mode data connection for
        gcc-2.5.0-2.5.2.diff.gz (43667 bytes).
    226 Transfer complete.
    43667 bytes received in 19 seconds (2.298 Kbytes/s)
    mget gcc-2.5.1-2.5.2.diff.gz?n        we don't need this one
    mget gcc-2.5.2-2.5.3.diff.gz?y
    200 PORT command successful.
    150 Opening BINARY mode data connection for
      gcc-2.5.2-2.5.3.diff.gz (78731 bytes).
    226 Transfer complete.
    78731 bytes received in 33 seconds (2.835 Kbytes/s)
    ... etc
    

    prompt

    Using mget saves a lot of network bandwidth and copies the files faster, but it has one disadvantage: ftp prompts you for each file name, so you have to wait around to answer the prompts. If you don't, ftp disconnects after 15 minutes of inactivity. It would be simpler to perform all the mgets without any intervention. This is where the prompt command comes in.

    The prompt command specifies whether to issue certain prompts or not—the mget command is one example. This command is a toggle—in other words, if prompting is on, prompt turns it off, and if prompting is off, prompt turns it on. If prompting is off, the mget command in the previous example would have gone through with no interruptions.

    In the previous example, you don't really want to transfer the file gcc-2.5.1-2.5.2.diff.gz, because you don't need it to perform the patches: you can upgrade from 2.5.0 to 2.5.2 directly with the file gcc-2.5.0-2.5.2.diff.gz. On the other hand, not copying the file would mean sitting around for the duration of the transfer and answering the prompt for each file, and the file is only 1 kB long. In this case, it is reasonable to copy it as well-in other cases; you may need to consider alternatives.

    reget

    Sooner or later, you will lose a connection in the middle of a transfer. According to Murphy's law, this will usually happen with a big file, and it will be shortly before the transfer is finished. You may be able to save the day with reget, which picks up the transfer where it left off. The scodeantics are the same as for get.

    Unfortunately, not all versions of ftp have the reget command, and on many systems that do have the command, it doesn't work correctly. If you do decide to use it, you should first make a copy of the partially copied file, in case something goes wrong.

    user

    Normally, ftp attempts to log in using the user name of the user who started the ftp program. To make establishing connections easier, ftp checks for a file called .netrc when performing a login sequence. .netrc contains information on how to log in to specific systems. A typical .netrc might look like:

    machine freebie  login grog  password foo
    machine presto   login grog  password bar
    machine bumble   login grog  password baz
    machine wait     login grog  password zot
    default          login ftp   password grog@example.org
    

    Lines starting with the keyword machine specify login name (grog in this example) and password for each system. The last line is the important one: if the system is not mentioned by name, ftp attempts a login with user name ftp and password grog@example.org. Though this may be of use with systems you don't know, it causes a problem: if you want to connect to a machine without anonymous ftp, you will need to explicitly tell ftp not to attempt an auto-login. Do this with the -n option:

    $ ftp -n ftp.remote.org
    

    The .netrc file is a security risk: it contains all your passwords in readable form. Make sure it is secured so that only you can read or write it.

    ftp is not overly clear about login failures. For example,

    $ ftp ftp.tu-darmstadt.de
    Connected to ftp.tu-darmstadt.de.
    220 rs3.hrz.th-darmstadt.de FTP server (Version 4.1) ready.
    331 Password required for grog.
    530 Login incorrect.
    Login failed.
    Remote system type is UNIX.
    Using binary mode to transfer files.
    ftp>
    

    This error message is not very obvious: although you're not logged in, you still get the same prompt, and ftp produces enough verbiage that it's easy to oversee that the login attempt failed. To complete the login, use the user command:

    ftp> user ftp
    331 Guest login ok, send ident as password.
    Password:                  password does not echo
    230 Guest login ok, access restrictions apply.
    

    sftp

    sftp is yet another ssh-based program. It's designed to be as compatible as possible with ftp, so you use it in exactly the same manner. As with other ssh-related commands, you need to authenticate in an ssh-specific manner. In addition, it has an exec command, which allows you to run programs on the remote machine.

    To use sftp, the remote machine must be able to run the sftp-server server. It is normally started from sshd. See page 454 for more details.

    rsync

    Frequently you want to keep identical copies of files on different machines. You can copy them, of course, but if there are only small changes in large files, this can be relatively inefficient. You can perform this task more efficiently with rsync, which is designed to keep identical copies of files on two different systems and to optimize network bandwidth while doing so. It's in the Ports Collection. Install in the normal manner:

    # cd /usr/ports/net/rsync
    # make install
    

    By default, rsync uses ssh to perform the transfer, so you need to have ssh configured correctly. In particular, you should be using ssh-agent authentication.

    You can use rsync like scp: the syntax is compatible up to a point. For example, you could copy a file from a remote system with:

    $ rsync presto:/var/log/messages prestomessages
    

    You don't need to install rsync just for that, of course: you can do exactly the same thing with scp. rsync has one advantage over scp, how ever, even in this case. The first time you copy the file, there's no difference. But files like /var/log/messages grow at the end, and the rest doesn't change. That's an ideal situation for rsync: it uses an algorithm that recognizes common parts of files (not necessarily at the beginning) and optimizes the transfer accordingly. The first time you run the program, you might see:

    $ rsync -v /var/log/messages freebie:/var/tmp
    messages
    wrote 80342 bytes  read 36 bytes  53585.33 bytes/sec
    total size is 80255  speedup is 1.00
    $ rsync -v /var/log/messages freebie:/var/tmp
    messages
    wrote 535 bytes  read 726 bytes  840.67 bytes/sec
    total size is 80255  speedup is 63.64
    

    This example used the option -v to show details of what was transferred; otherwise you wouldn't see any output at all. The first time round, the entire file was copied, so there was no speed up. The second time, though, almost nothing needed to be copied, so the transfer was over 60 times as fast.

    Copying directory hierarchies

    rsync has a bewildering number of options for synchronizing directories. Consider the case where you maintain web pages locally, but your main web server is co-located somewhere else. After updating the local web pages, you can run a script to update the remote pages with commands like:

    rsync -LHzav --exclude=RCS --exclude="*~" ~grog/public_html/* website:htdocs/grog
    rsync -LHztpgov --exclude="*~" website:htdocs
    

    The first rsync command synchronizes the local directory ~grog/public_html to the remote directory htdocs/grog on the system website. It includes all subdirectories with the exception of the RCS directories. The second command synchronizes the top level web directory only, and not the subdirectories, many of which shouldn't be maintained on the remote site. In each case, files ending in ~ are excluded (these are normally Emacs backup files), and in the second case the RCS subdirectories are also excluded. Let's look more carefully at all those options:

  • -L copies symbolic links (which the documentation refers to as "soft links") as separate files. If you don't include this option, symbolic links to files within the directory hierarchy will work, but links outside the hierarchy may be broken (depending on whether a file of that name exists on the destination system or not). In this example, a number of files are really located elsewhere, so it makes sense to copy them as files.
  • -H is pretty much the opposite of -L: by default, rsync doesn't check whether it has already copied a file, so if it finds another link to it, it will create a new file on the remote machine. -H tells it to keep track of links and simply create another link to any file it has already copied on the destination machine. This can only work if the two links have been copied by the same invocation of rsync.
  • The option -z tells rsync to compress data. This can significantly reduce traffic.
  • The option -a ("archive") is in fact a shorthand notation for a total of seven other options. We'll see some of them below. The others are:
  • -r: copy subdirectories recursively.
  • -l: create symbolic links where necessary. In this example, it's overruled by the -L option.
  • -D: copy device nodes (only for root).
  • The other options are -p, -t, -g and -o. We don't want to copy subdirectories in the second example, so we state them explicitly. Together, they roughly correspond to the -p (preserve) option to some other copy programs.

  • The option -p tells rsync to set the permissions of the remote copy to be the same as those of the original file.
  • The option -t tells rsync to preserve the modification times of the original file on the remote copy.
  • The option -g tells rsync to set the group ownership of the remote copy to be the same as those of the original file.
  • The option -o tells rsync to set the ownership of the remote copy to be the same as those of the original file.
  • We've already seen the -v option: it gives information on what rsync is doing.
  • When copying directories with rsync, it's relatively easy to end up with the files in the wrong directory level: either they're in the parent directory, or in a subdirectory of the same name. Consider the following command to synchronize a mail folder to a laptop:

    $ cd /home/grog
    $ rsync -zHLav presto:/home/grog/Mail Mail
    

    This would seem to duplicate the directory /home/grog/Mail on the remote system to a directory of the same name on the local system. In fact, it moves the contents of the host /home/grog/Mail to /home/grog/Mail/Mail on the local machine. To do what you expect, write:

    $ rsync -zHLav presto:/home/grog/Mail .
    

    Using an rsync server

    The use of rsync that we've seen so far doesn't require a server, but it does require an ssh. rsync also offers a different means of access that uses a server, rsyncd. This method is intended more for access to systems for which you don't have a password, something like anonymous ftp.

    We'll look at setting up an rsync server on page 454. The client side is relatively simple. Use two colons when referring to the remote system. For example, you might enter:

    $ rsync freebie::
    This is freebie.example.org.  Be gentle.
    
    groggy  Greg's web pages
    tivo    TiVo staging area
    

    The first line is simply an identification message, referred to as a message of the day in the documentation. The others represent directory hierarchies that the server makes available, along with a comment about their purpose. The documentation calls them modules. As we'll see on page 454, they correspond to directories on the server machine, though the names don't need to be related.

    To find out what is in these directories, you can use the following kind of command, which specifies a particular module, but no destination:

    $ rsync freebie::groggy
    This is freebie.example.org.   Be gentle.
    drwxr-xr-x    5632 2002/10/24 12:40:38 .
    -rw-r--r--    3855 2002/03/16 13:51:12 20feb99.html
    -rw-r--r--    2363 2002/03/16 13:51:12 7mar1999.html
    -rw-r--r--    8345 2002/03/16 13:51:12 AOSS-programme-orig.html
    -rw-r--r--   11590 2002/03/16 13:51:12 AOSS-programme.html
    -rw-r--r--    1798 2002/03/16 13:51:12 BSDCon-2002.html
    -rw-r--r--    1953 2002/03/16 13:51:12 Essey-20020222.html
    ...etc
    

    To transfer a file, specify its name and a destination:

    $ rsync -v freebie::groggy/AOSS-programme.html .
    This is freebie.example.org.  Be gentle.
    
    AOSS-programme.html
    wrote 98 bytes  read 11744 bytes  23684.00 bytes/sec
    total size is 11590  speedup is 0.98
    

    This example uses the -v option to show what rsync has done; without it, there would be no output.

    If you want to transfer the entire module, use the -r or -a options we looked at above:

    $ rsync -r -v freebie::groggy .
    This is freebie.example.org.   Be gentle.
    
    receiving file list ... done
    skipping non-regular file "Images/20001111"
    20feb99.html
    7mar1999.html
    AOSS-programme-orig.html
    AOSS-programme.html
    BSDCon-2002.html
    ...etc
    

    The Network File System

    The Network File System, or NFS, is the standard way to share UNIX files across a network.

    We've already seen that UNIX file systems are accessible in a single tree by mounting them on a specific directory. NFS continues this illusion across the network.

    From a user point of view, there is little difference: you use the same mount command, and it performs what looks like the same function. For example, if system presto's system administrator wants to mount freebie's file systems, /usr and /home, he could enter:

    # mkdir    /freebie
    # mount    freebie:/  /freebie
    # mount    freebie:/usr  /freebie/usr
    # mount    freebie:/home  /freebie/home
    

    You'll note how to specify the file systems: the system name, a colon (:), and the file system name. This terminology predates URIs; nowadays, people would probably write nfs://freebie/usr.

    Note also that you don't need to create /freebie/usr and /freebie/home :assuming that the directories /usr and /home exist on once you have mounted /freebie, they will become visible.

    If you look at NFS more closely, things don't look quite as similar to disks as they do at first sight. You access local file systems via the disk driver, which is part of the kernel. You access NFS file systems via the NFS processes.

    Older implementations of NFS had a plethora of processes. If you're used to such systems, don't let the lack of processes make you think that there's something missing.

    NFS client

    You don't need any particular software to run as an NFS client, but the program nfsiod greatly improves performance. It's started at boot up time if you specify nfs_client_enable="YES" in your /etc/rc.conf, but you can also start it manually if it's not running:

    # nfsiod -n 6
    

    The parameter -n 6 tells nfsiod how many copies of itself to start. The default is four. Each nfsiod can handle a concurrent I/O request, so if you find that your performance isn't what you would like it to be, and the CPU time used by each nfsiod is similar, then you might like to increase this value. To ensure it's done automatically at boot time, add the following to /etc/sysctl.conf:

    vfs.nfs.iothreads=6
    

    We'll look at /etc/rc.conf and /etc/sysctl.conf in more detail in Chapter 29.

    Mounting remote file systems

    As we've seen, we mount NFS files with the same mount command that we use for local file systems. This is another illusion: mount is just a front-end program that determines which program to start. In the case of local file systems, it will start mount_ufs, and for NFS file systems it will start mount_nfs.

    There are a number of options you may wish to use when mounting NFS file systems. Unfortunately, the options that mount_nfs uses are not the same as the options you would use in /etcfstab. Here's an over view:

    NFS mount options
    fstab optionmount_nfs optionMeaning
    bg-bContinue attempting the mount in the background if it times out on the initial attempt. This is a very good idea in /etc/ftab, because otherwise the boot process waits until all mounts have completed. If you've just had a power failure, this can cause deadlocks otherwise.
    nfsv2-2Use NFS Version 2 protocol. By default, mount_nfs tries NFS Version 3 protocol first, and falls back to Version 2 if the other end can't handle Version 3. Don't use NFS Version 2 unless you have to.
    retry=num-RnumRetry up to num times before aborting an I/O operation.
    -o ro-o roMount the file system for read-only access.
    -o rw-o rwMount the file system for read and write access.
    -R num-R numRetry the mount operation up to num times. If you have chosen soft mounting, fail I/O operations after num retries. The default value is 10.
    -r .size-r .sizeSet the read data block size to size bytes. size should be a power of 2 between 1024 and 32768. The default value is 8192. Use smaller block sizes for UDP mounts if you have frequent fragments dropped due to timeout messages on the client.
    soft-sIf operations on the file system time out, don't retry forever. Instead, give up after Retry timeouts. See option -R.
    -t num-t numTime out and retry an operation if it doesn't complete with in num 10 seconds. The default value is 10 (1 second).
    tcp-TUse TCP instead of UDP for mounts. This is more reliable, but slightly slower. In addition, not all implementations of NFS support TCP transport.
    -w .size- .sizeSet the write data block size to size bytes. size should be a power of 2 between 1024 and 32768. The default value is 8192. Use smaller block sizes for UDP mounts if you have frequent "fragments dropped due to timeout" messages on the server.

    Normally, the only options that are of interest are -o ro, if you specifically want to restrict write access to the file system, and soft, which you should always use.

    Purists claim that soft compromises data integrity, because it may leave data on the server machine in an unknown state. That's true enough, but in practice the alternative to soft mounting is to reboot the client machine. This is not only a nuisance, it also compromises data integrity. The only solution that doesn't always compromise data integrity is to wait for the server machine to come back online. It's unlikely that anybody will wait more than a few hours at the outside for a server to come back.

    A typical mount operation might be:

    # mount -o soft presto:/usr /presto/usr
    

    Where to mount NFS file systems

    You can mount an NFS file system just about anywhere you would mount a local file system. Still, a few considerations will make life easier. In this discussion, we'll assume that we have a large number of file systems mounted on freebie, and we want to make them accessible to presto.

  • If you have a "special" file system that you want to mount on multiple systems, it makes sense to mount it on the same mount point on every system. freebie has two file systems, /S and /src, which contain source files and are shared between all systems on the network. It makes sense to mount the file system on the same directory.
  • freebie has a CD-ROM changer, and mounts the disks on /cdrom/1 to /cdrom/7. presto finds that too confusing, and mounts one of them on /cdrom.
  • Some other file systems can't be mounted in the same place. For example, freebie:/usr can't be mounted on /usr. Mount them on directories that match the system name. For example, mount freebie:/usr on /freebie/usr.
  • After doing this, you might find the following file systems mounted on freebie:

    # df
    Filesystem   1024-blocks     Used   Avail  Capacity  Mounted on
    /dev/ad0s1a        30206    26830     960     97%    /
    /dev/ad0s1e      1152422  1016196   44034     96%    /usr
    /dev/da0h         931630   614047  243052     72%    /src
    /dev/dalh        2049812  1256636  629192     67%    /home
    procfs                 4        4       0    100%    /proc
    /dev/cd0a         656406   656406       0    100%    /cdrom/1
    /dev/cdla         664134   664134       0    100%    /cdrom/2
    /dev/cd2a         640564   640564       0    100%    /cdrom/3
    /dev/cd3a         660000   660000       0    100%    /cdrom/4
    /dev/cd4a         525000   525000       0    100%    /cdrom/5
    /dev/cd5a         615198   615198       0    100%    /cdrom/6
    /dev/cd6a         278506   278506       0    100%    /cdrom/7
    

    On presto, you might see:

    # df
    Filesystem    1024-blocks     Used    Avail  Capacity    Mounted on
    /dev/da0s1a         29727    20593     6756     75%      /
    /dev/da0s1e       1901185   742884  1006207     42%      /usr
    procfs                  4        4        0    100%      /proc
    freebie:/           30206    26830      960     97%      /freebie
    freebie:/usr      1152422  1016198    44032     96%      /freebie/usr
    freebie:/home     2049812  1256638   629190     67%      /home
    freebie:/src       931630   614047   243052     72%      /src
    freebie:/S        3866510  1437971  2119219     40%      /S
    freebie:/cdrom/1   656406   656406        0    100%      /cdrom
    

    Mounting NFS file systems automatically

    If you want to mount NFS files automatically at boot time, make an entry for them in the file /etc/fstab. You can even do this if you don't necessarily want to mount them: just add the keyword noauto, and mountall will ignore them at boot time. The advantage is that you then just need to specify, say,

    # mount /src
    

    instead of:

    # mount -s freebie:/src /src
    

    See the description of /etc/fstab on page 566 for more information.

    NFS strangenesses

    NFS mimics a local file system across the network. It does a pretty good job, but it's not perfect. Here are some things that you should consider.

    No devices

    NFS handles disk files and directories, but not devices. Actually, it handles devices too, but not the way you would expect.

    In a UNIX file system, a device is more correctly known as a device node: it's an inode that describes a device in terms of its major and minor numbers (see page 195). The device itself is implemented by the device driver. NFS exports device nodes in UFS file systems, but it doesn't interpret the fact that these devices are on another system. If you refer to the devices, one of three things will happen:

  • If a driver for the specified major number exists on your local system, and the devices are the same on both systems, you will access the local device. Depending on which device it is, this could create some subtle problems that could go undetected for quite awhile.
  • If a driver for the specified major number exists on your local system, and the devices are different on the two systems, you will still access the local device with the same major and minor numbers, if such a device exists. The results could be very confusing.
  • If no driver for the specified major number exists on your local system, the request will fail. This can still cause considerable confusion.
  • If the NFS server system runs devfs, the device nodes are not exported. You won't see anything unless there are left over device nodes from before the time of migration to devfs.

    Just one file system

    NFS exports file systems, not directory hierarchies. Consider the example on page 444. presto has mounted both freebie:/ and freebie:/usr. If it were just to mount freebie:/, we would see the directory /freebie/usr, but it would be empty.

    Things can get even stranger: you can mount a remote file system on a directory that is not empty. Consider the following scenario:

  • You install FreeBSD on system feebie. In single-user mode, before mounting the other file systems, you create a directory /usr/bin and a file /usr/bin/vi. Since the /usr file system isn't mounted, this file goes onto the root file system.
  • You go to multi-user mode and mount the other file systems, including the file system for /usr. You can no longer see the /usr/bin/vi you put there in single-user mode. It hasn't gone away, it's just masked.
  • On presto, you mount the file system freebie:/ on freebie. If you list the contents of the directory /freebie/usr, you will see the original file vi, and not the contents that the users on freebie will see.
  • Вернуться к учебному плану