Chapter 10. Network Applications and Services(网络应用和服务)

This chapter explores basic network applications—the clients and servers running in user space that reside at the application layer. Because this layer is at the top of the stack, close to end users, you may find this material more accessible than the material in Chapter 9. Indeed, you interact with network client applications such as web browsers and email readers every day.

本章探讨基本的网络应用程序——在用户空间运行的客户端和服务器,这些客户端和服务器位于应用层。

因为这一层位于堆栈的顶部,靠近最终用户,所以您可能会发现这部分材料比第9章中的材料更易理解。

事实上,您每天都会与诸如网络浏览器和电子邮件阅读器之类的网络客户端应用程序进行交互。

To do their work, network clients connect to corresponding network servers. Unix network servers come in many forms. A server program can listen to a port on its own or through a secondary server. In addition, servers have no common configuration database and a wide variety of features. Most servers have a configuration file to control their behavior (though with no common format), and most use the operating system’s syslog service for message logging. We’ll look at some common servers as well as some tools that will help you understand and debug server operation.

为了完成其工作,网络客户端连接到相应的网络服务器。Unix网络服务器有许多形式。服务器程序可以通过自身或通过辅助服务器监听端口。

此外,服务器没有通用的配置数据库,具有各种各样的功能。

大多数服务器都有一个配置文件来控制其行为(尽管没有通用格式),并且大多数使用操作系统的syslog服务进行消息记录。

我们将研究一些常见的服务器以及一些工具,这些工具将帮助您理解和调试服务器的运行。

Network clients use the operating system’s transport layer protocols and interfaces, so understanding the basics of the TCP and UDP transport layers is important. Let’s start looking at network applications by experimenting with a network client that uses TCP.

网络客户端使用操作系统的传输层协议和接口,因此了解TCP和UDP传输层的基础知识非常重要。

让我们通过尝试使用TCP的网络客户端来开始研究网络应用程序。

10.1 The Basics of Services

TCP services are among the easiest to understand because they are built upon simple, uninterrupted two-way data streams. Perhaps the best way to see how they work is to talk directly to a web server on TCP port 80 to get an idea of how data moves across the connection. For example, run the following command to connect to a web server:

TCP服务是最容易理解的服务之一,因为它们建立在简单、不间断的双向数据流之上。

也许最好的方法是直接与 TCP 端口 80 上的 Web 服务器进行通信,以了解它们是如何工作的。

例如,运行以下命令连接到 Web 服务器:

$ telnet www.wikipedia.org 80

You should get a response like this:

你应该会得到如下响应:

Trying some address... 
Connected to www.wikipedia.org. 
Escape character is '^]'. 

Now enter

现在输入

GET / HTTP/1.0

Press ENTER twice. The server should send a bunch of HTML text as a response and then terminate the connection.

按两次 ENTER 键。服务器应该会发送一堆 HTML 文本作为响应,然后终止连接。

This exercise tells us that

这个练习告诉我们:

o the remote host has a web server process listening on TCP port 80; and
o telnet was the client that initiated the connection.

  • 远程主机上有一个监听 TCP 端口 80 的 Web 服务器进程;以及
  • telnet 是启动连接的客户端。

NOTE telnet is a program originally meant to enable logins to remote hosts. Although the non Kerberos telnet remote login server is completely insecure (as you will learn later), the telnet client can be useful for debugging remote services. telnet does not work with UDP or any transport layer other than TCP. If you’re looking for a general-purpose network client, consider netcat, described in 10.5.3 netcat.

注意:telnet 是一个最初用于启用登录到远程主机的程序。

尽管非 Kerberos telnet 远程登录服务器是完全不安全的(稍后你将了解),但 telnet 客户端可用于调试远程服务。

telnet 不支持 UDP 或除 TCP 外的任何传输层。

如果你正在寻找通用网络客户端,请考虑 netcat,详情请参见 10.5.3 netcat。

10.1.1 A Closer Look

In the example above, you manually interacted with a web server on the network with telnet, using the Hypertext Transfer Protocol (HTTP) application layer protocol. Although you’d normally use a web browser to make this sort of connection, let’s take just one step up from telnet and use a command-line program that knows how to speak to the HTTP application layer. We’ll use the curl utility with a special option to record details about its communication:

在上面的示例中,您通过telnet手动与网络上的Web服务器进行了交互,使用了超文本传输协议(HTTP)应用层协议。

虽然通常您会使用Web浏览器来建立这种连接,但让我们从telnet再向上迈进一步,使用一个能够与HTTP应用层通信的命令行程序。

我们将使用curl实用程序,并加上一个特殊选项来记录其通信的详细信息:

$ curl --trace-ascii trace_file http://www.wikipedia.org/

NOTE Your distribution may not have the curl package preinstalled, but you should have no trouble installing it if necessary.

注意:您的发行版可能没有预安装curl软件包,但如果需要安装它,您应该没有任何问题。

You’ll get a lot of HTML output. Ignore it (or redirect it to /dev/null) and instead look at the newly created file trace_file. Assuming that the connection was successful, the first part of the file should look something like the following, at the point where curl attempts to establish the TCP connection to the server:

您将获得大量HTML输出。请忽略它(或将其重定向到/dev/null),而是查看新创建的文件trace_file。

假设连接成功,文件的第一部分应该类似于以下内容,在curl尝试建立与服务器的TCP连接时:

== Info: About to connect() to www.wikipedia.org port 80 (#0) 
== Info:   Trying 10.80.154.224... == Info: connected

Everything you’ve seen so far happens in the transport layer or below. However, if this connection succeeds, curl tries to send the request (the “header”); this is where the application layer starts:

到目前为止,你所看到的一切都发生在传输层或以下。

然而,如果此连接成功,curl 尝试发送请求(即“头部”);这是应用层开始的地方。

=> Send header, 167 bytes (0xa7) 
0000: GET / HTTP/1.1 
0010: User-Agent: curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenS 
0050: SL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3 
007f: Host: www.wikipedia.org 
0098: Accept: */* 
00a5: 

The first line here is curl debugging output telling you what it will do next. The remaining lines show what curl sends to the server. The text in bold is what goes to the server; the hexadecimal numbers at the beginning are just debugging offsets from curl to help you keep track of how much data was sent or received.

这里的第一行是curl调试输出,告诉您接下来将要执行的操作。

其余行显示了curl发送到服务器的内容。

粗体文本是发送到服务器的内容;开头的十六进制数字只是curl的调试偏移量,帮助您跟踪发送或接收了多少数据。

You can see that curl starts by issuing a GET command to the server (as you did with telnet), followed by some extra information for the server and an empty line. Next, the server sends a reply, first with its own header, shown here in bold:

您可以看到,curl首先向服务器发出一个GET命令(就像您在telnet中所做的那样),然后是一些额外的信息和一个空行。

接下来,服务器发送了一个回复,首先是自己的头部,如下所示:

<= Recv header, 17 bytes (0x11) 
0000: HTTP/1.1 200 OK 
<= Recv header, 16 bytes (0x10) 
0000: Server: Apache 
<= Recv header, 42 bytes (0x2a) 
0000: X-Powered-By: PHP/5.3.10-1ubuntu3.9+wmf1 --snip--

Much like the previous output, the <= lines are debugging output, and 0000: precedes the lines of output to tell you offsets.

与之前的输出类似,<= 行是调试输出,0000:在输出行之前告诉您偏移量。

The header in the server’s reply can be fairly long, but at some point the server transitions from transmitting headers to sending the actual requested document, like this:

服务器回复中的标题可能相当长,但在某个时刻,服务器从传输标题转变为发送实际请求的文档,就像这样:

<= Recv header, 55 bytes (0x37) 
0000: X-Cache: cp1055 hit (16), cp1054 frontend hit (22384) 
<= Recv header, 2 bytes (0x2) 
0000: 
<= Recv data, 877 bytes (0x36d) 
0000: 008000 
0008: <!DOCTYPE html>.<html lang="mul" dir="ltr">.<head>.<!-- Sysops: --snip-- 

This output also illustrates an important property of the application layer. Even though the debugging output says Recv header and Recv data, implying that those are two different kinds of messages from the server, there’s no difference in the way that curl talked to the operating system to retrieve the two kinds of messages, nor any difference in how the operating system handled them, nor any difference in the way that the network handled the packets underneath. The difference is entirely within the user-space curl application itself. curl knew that until this point it had been getting headers, but when it received a blank line (the 2 byte chunk in the middle) signifying the end of headers in HTTP, it knew to interpret anything that followed as the requested document.

这个输出还展示了应用层的一个重要特性。

尽管调试输出中显示“接收头部”和“接收数据”,暗示这两种消息来自服务器,但在 curl 与操作系统交互以获取这两种消息的方式、操作系统处理它们的方式以及网络在底层处理数据包的方式上并没有任何区别。

区别完全在于用户空间中的 curl 应用程序本身。

curl 知道直到这一点它一直在接收头部,但当它收到一个空行(中间的 2 字节块)表示 HTTP 头部结束时,它就知道要将接下来的任何内容解释为请求的文档。

The same is true of the server sending this data. When sending the reply, the server didn’t differentiate between header and document data sent to the operating system; the distinctions happen inside the user-space server program.

发送这些数据的服务器也是如此。

在发送回复时,服务器没有区分发送到操作系统的头部数据和文档数据;区别发生在用户空间服务器程序内部。

10.2 Network Servers

Most network servers are like other server daemons on your system such as cron, except that they interact with network ports. In fact, recall syslogd discussed in Chapter 7; it accepts UDP packets on port 514 when started with the -r option.

大多数网络服务器与系统中的其他服务器守护进程(如cron)类似,只是它们与网络端口进行交互。

事实上,回想一下第7章讨论过的syslogd;当使用-r选项启动时,它会在514端口接受UDP数据包。

These are some other common network servers that you might find running on your system:

以下是一些你可能在系统上发现正在运行的常见网络服务器:

o httpd, apache, apache2 Web servers
o sshd Secure shell daemon (see 10.3 Secure Shell (SSH))
o postfix, qmail, sendmail Mail servers
o cupsd Print server
o nfsd, mountd Network filesystem (file-sharing) daemons
o smbd, nmbd Windows file-sharing daemons (see Chapter 12)
o rpcbind Remote procedure call (RPC) portmap service daemon

  • httpd、apache、apache2 网页服务器
  • sshd 安全外壳守护进程(参见10.3 安全外壳(SSH))
  • postfix、qmail、sendmail 邮件服务器
  • cupsd 打印服务器
  • nfsd、mountd 网络文件系统(文件共享)守护进程
  • smbd、nmbd Windows 文件共享守护进程(参见第12章)
  • rpcbind 远程过程调用(RPC)端口映射服务守护进程

One feature common to most network servers is that they usually operate as multiple processes. At least one process listens on a network port, and when a new incoming connection is received, the listening process uses fork() to create a new child process, which is then responsible for the new connection. The child, often called a worker process, terminates when the connection is closed. Meanwhile, the original listening process continues to listen on the network port. This process allows a server to easily handle many connections without much trouble.

大多数网络服务器的一个共同特点是它们通常作为多个进程运行。

至少有一个进程在监听网络端口,当接收到新的传入连接时,监听进程使用fork()创建一个新的子进程,然后该子进程负责处理新连接。

子进程通常被称为工作进程,在连接关闭时终止。与此同时,原始的监听进程继续监听网络端口。

这个过程使得服务器能够轻松处理许多连接而不会出现太多问题。

There are some exceptions to this model, however. Calling fork() adds a significant amount of system overhead. In comparison, high-performance TCP servers such as the Apache web server can create a number of worker processes upon startup so that they are already there to handle connections as needed. Servers that accept UDP packets simply receive data and react to it; they don’t have connections to listen for.

然而,也有一些例外情况。调用fork()会增加大量系统开销。

相比之下,高性能的TCP服务器(如Apache Web服务器)可以在启动时创建多个工作进程,以便在需要时立即处理连接。

接受UDP数据包的服务器只需接收数据并对其做出反应;它们不需要监听连接。

10.3 Secure Shell (SSH)

Every server works a bit differently. Let’s take a close look at one—the standalone SSH server. One of the most common network service applications is the secure shell (SSH), the de facto standard for remote access to a Unix machine. When configured, SSH allows secure shell logins, remote program execution, simple file sharing, and more—replacing the old, insecure telnet and rlogin remote-access systems with public-key cryptography for authentication and simpler ciphers for session data. Most ISPs and cloud providers require SSH for shell access to their services, and many Linux-based network appliances (such as NAS devices) allow access via SSH as well. OpenSSH (http://www.openssh.com/) is a popular free SSH implementation for Unix, and nearly all Linux distributions come with it preinstalled. The OpenSSH client is ssh, and the server is sshd. There are two main SSH protocol versions: 1 and 2. OpenSSH supports both, but version 1 is rarely used.

每个服务器的工作方式都有所不同。让我们仔细看看其中一个——独立的SSH服务器。

安全外壳(SSH)是最常见的网络服务应用程序之一,也是远程访问Unix机器的事实标准。

配置好后,SSH允许安全外壳登录、远程程序执行、简单文件共享等功能,利用公钥加密进行身份验证以及简单密码算法处理会话数据,取代了旧的不安全的telnet和rlogin远程访问系统。

大多数互联网服务提供商和云服务提供商要求使用SSH来访问其服务的shell,许多基于Linux的网络设备(如NAS设备)也允许通过SSH访问。

OpenSSH(http://www.openssh.com/)是Unix上流行的免费SSH实现,几乎所有Linux发行版都预装了它。

OpenSSH客户端是ssh,服务器是sshd。SSH有两个主要协议版本:1和2。

OpenSSH支持两者,但很少使用第1版。

Among its many useful capabilities and features, SSH does the following:

在其许多有用功能和特性中,SSH可以实现以下功能:

o Encrypts your password and all other session data, protecting you from snoopers.
o Tunnels other network connections, including those from X Window System clients. You’ll learn more about X in Chapter 14.
o Offers clients for nearly any operating system.
o Uses keys for host authentication.

  • 加密密码和所有其他会话数据,保护您免受窥探。
  • 隧道化其他网络连接,包括来自X Window系统客户端的连接。您将在第14章中更多地了解关于X的内容。
  • 为几乎任何操作系统提供客户端。
  • 使用密钥进行主机身份验证。

NOTE Tunneling is the process of packaging and transporting one network connection using another one. The advantages of using SSH to tunnel X Window System connections are that SSH sets up the display environment for you and encrypts the X data inside the tunnel.

注意:隧道是使用另一个网络连接打包和传输一个网络连接的过程。

使用SSH进行X Window系统连接隧道化的优势在于SSH为您设置显示环境并在隧道内加密X数据。

SSH does have its disadvantages. For one, in order to set up an SSH connection, you need the remote host’s public key, and you don’t necessarily get it in a secure way (though you can check it manually to make sure you’re not being spoofed). For an overview of how several methods of cryptography work, get your hands on the book Applied Cryptography: Protocols, Algorithms, and Source Code in C, 2nd edition, by Bruce Schneier (Wiley, 1996). Two in-depth books on SSH are SSH Mastery: OpenSSH, PuTTY, Tunnels and Keys by Michael W. Lucas (Tilted Windmill Press, 2012) and SSH, The Secure Shell, 2nd edition, by Daniel J. Barrett, Richard E. Silverman, and Robert G. Byrnes(O’Reilly, 2005).

SSH也有其缺点。首先,在建立SSH连接时,您需要远程主机的公钥,并且不一定以安全的方式获取(尽管您可以手动检查以确保没有被欺骗)。

要了解几种加密方法的概述,请阅读

  • Bruce Schneier的《应用密码学:C语言协议、算法和源代码》第2版(Wiley,1996)。

关于SSH的两本深入书籍是

  • Michael W. Lucas的《SSH技巧:OpenSSH、PuTTY、隧道和密钥》(Tilted Windmill Press,2012)
  • Daniel J. Barrett、Richard E. Silverman和Robert G. Byrnes的《SSH,安全外壳》第2版(O'Reilly,2005)。

    10.3.1 The SSHD Server

Running sshd requires a configuration file and host keys. Most distributions keep configurations in the /etc/ssh configuration directory and try to configure everything properly for you if you install their sshd package. (The configuration filename sshd_config is easy to confuse with the client’s ssh_config setup file, so be careful.)

运行sshd需要一个配置文件和主机密钥。

大多数发行版将配置保存在/etc/ssh配置目录中,并在您安装他们的sshd软件包时尝试为您正确配置一切。

(配置文件名sshd_config很容易与客户端的ssh_config设置文件混淆,所以请小心。)

You shouldn’t need to change anything in sshd_config, but it never hurts to check. The file consists of keyword-value pairs, as shown in this fragment:

您不应该需要更改sshd_config中的任何内容,但检查一下也无妨。该文件由关键字-值对组成,如下所示:

Port 22 
#Protocol 2,1 
#ListenAddress 0.0.0.0 
#ListenAddress :: 
HostKey /etc/ssh/ssh_host_key 
HostKey /etc/ssh/ssh_host_rsa_key 
HostKey /etc/ssh/ssh_host_dsa_key

Lines beginning with # are comments, and many comments in your sshd_config might indicate default values. The sshd_config(5) manual page contains descriptions of all possible values, but these are the most important ones:

以#开头的行是注释,在你的sshd_config中的许多注释可能表示默认值。

sshd_config(5)手册页面包含所有可能值的描述,但以下是最重要的几个:

o HostKey file Uses file as a host key. (Host keys are described shortly.)
o LogLevel level Logs messages with syslog level level.
o PermitRootLogin value Permits the superuser to log in with SSH if value is set to yes. Set
value to no to prevent this.
o SyslogFacility name Logs messages with syslog facility name.
o X11Forwarding value Enables X Window System client tunneling if value is set to yes.
o XAuthLocation path Provides a path for xauth. X11 tunneling will not work without this path. If
xauth isn’t in /usr/bin, set path to the full pathname for xauth.

  • HostKey文件 使用文件作为主机密钥。(主机密钥将很快描述。)
  • LogLevel级别 记录具有syslog级别级别的消息。
  • PermitRootLogin值 如果值设置为yes,则允许超级用户使用SSH登录。将值设置为no可阻止此操作。
  • SyslogFacility名称 记录具有syslog设施名称的消息。
  • X11Forwarding值 如果值设置为yes,则启用X Window系统客户端隧道。
  • XAuthLocation路径 提供xauth的路径。如果未设置此路径,X11隧道将无法工作。如果xauth不在/usr/bin中,请将路径设置为xauth的完整路径名。

    Host Keys(主机密钥)

OpenSSH has three host key sets: one for protocol version 1 and two for protocol 2. Each set has a public key (with a .pub file extension) and a private key (with no extension). Do not let anyone see your private key, even on your own system, because if someone obtains it, you’re at risk from intruders.

OpenSSH有三组主机密钥:一组用于协议版本1,另外两组用于协议2。

每组都有一个公钥(扩展名为.pub文件)和一个私钥(没有扩展名)。

即使在您自己的系统上,也不要让任何人看到您的私钥,因为如果有人获取了它,您就会受到入侵者的威胁。

SSH version 1 has RSA keys only, and SSH version 2 has RSA and DSA keys. RSA and DSA are public key cryptography algorithms. The key filenames are given in Table 10-1.

SSH版本1仅使用RSA密钥,而SSH版本2使用RSA和DSA密钥。RSA和DSA是公钥加密算法。密钥文件名如下表所示。

Table 10-1. OpenSSH Key Files

表10-1. OpenSSH密钥文件

image.png

image.png

Normally you won’t need to build the keys because the OpenSSH installation program or your distribution’s installation script will do it for you, but you do need to know how to create keys if you plan to use programs like ssh-agent. To create SSH protocol version 2 keys, use the ssh-keygen program that comes with OpenSSH:

通常情况下,您不需要自己生成密钥,因为OpenSSH安装程序或您发行版的安装脚本会为您完成这些操作,但是如果您计划使用ssh-agent等程序,您需要了解如何创建密钥。

要创建SSH协议版本2的密钥,请使用随OpenSSH一起提供的ssh-keygen程序。

# ssh-keygen -t rsa -N '' -f /etc/ssh/ssh_host_rsa_key 
# ssh-keygen -t dsa -N '' -f /etc/ssh/ssh_host_dsa_key 

For the version 1 keys, use

对于版本 1 密钥,使用

# ssh-keygen -t rsa1 -N '' -f /etc/ssh/ssh_host_key

The SSH server and clients also use a key file called ssh_known_hosts, which contains public keys from other hosts. If you intend to use host-based authentication, the server’s ssh_known_hosts file must contain the public host keys of all trusted clients. Knowing about the key files is handy if you’re replacing a machine. When installing a new machine from scratch, you can import the key files from the old machine to ensure that users don’t get key mismatches when connecting to the new one.

SSH服务器和客户端还使用一个名为ssh_known_hosts的密钥文件,其中包含其他主机的公钥。

如果您打算使用基于主机的身份验证,服务器的ssh_known_hosts文件必须包含所有受信任客户端的公共主机密钥。

了解关于密钥文件的信息对于更换计算机很有用。

当从头开始安装新计算机时,您可以从旧计算机导入密钥文件,以确保用户在连接到新计算机时不会出现密钥不匹配的情况。

Starting the SSH Server(启动SSH服务器)

Although most distributions ship with SSH, they usually don’t start the sshd server by default. On Ubuntu and Debian, installing the SSH server package creates the keys, starts the server, and adds the startup to the bootup configuration. On Fedora, sshd is installed by default but turned off. To start sshd at boot, use chkconfig like this (this won’t start the server immediately; use service sshd start for that):

虽然大多数发行版都预装了SSH,但它们通常不会默认启动sshd服务器。在Ubuntu和Debian上,安装SSH服务器包会创建密钥、启动服务器,并将启动配置添加到启动项中。

在Fedora上,默认安装了sshd,但是处于关闭状态。

要在启动时启动sshd,请使用chkconfig命令(这不会立即启动服务器;要立即启动服务器,请使用service sshd start命令)。

# chkconfig sshd on 

Fedora normally creates any missing host key files upon the first sshd startup.

Fedora通常会在第一次启动sshd时创建任何缺失的主机密钥文件。

If you don’t have any init support installed yet, running sshd as root starts the server, and upon startup, sshd writes its PID to /var/run/sshd.pid.

如果您尚未安装任何init支持,以root身份运行sshd将启动服务器,并在启动时将其PID写入/var/run/sshd.pid。

You can also start sshd as a socket unit in systemd or with inetd, but it’s usually not a good idea to do so because the server occasionally needs to generate key files, a process that can take a long time.

您也可以将sshd作为systemd中的套接字单元或使用inetd启动,但通常不建议这样做,因为服务器有时需要生成密钥文件,这个过程可能需要很长时间。

10.3.2 The SSH Client(SSH客户端)

To log in to a remote host, run

要登录到远程主机,请运行:

$ ssh remote_username@host

You may omit remote_username@ if your local username is the same as on host. You can also run pipelines to and from an ssh command as shown in the following example, which copies a directory dir to another host:

如果您的本地用户名与主机上的相同,则可以省略remote_username@。

您还可以像以下示例中所示运行到ssh命令的管道,该示例将一个目录dir复制到另一台主机:

$ tar zcvf - dir | ssh remote_host tar zxvf - 

The global SSH client configuration file ssh_config should be in /etc/ssh with your sshd_config file. As with the server configuration file, the client configuration file has key-value pairs, but you shouldn’t need to change them.

全局SSH客户端配置文件ssh_config应该位于/etc/ssh目录下,与您的sshd_config文件一起。

与服务器配置文件一样,客户端配置文件也有键值对,但您不应该需要更改它们。

The most frequent problem with using SSH clients occurs when an SSH public key in your local ssh_known_hosts or .ssh/known_hosts file does not match the key on the remote host. Bad keys cause errors or warnings like this:

使用SSH客户端时最常见的问题是,本地ssh_known_hosts或.ssh/known_hosts文件中的SSH公钥与远程主机上的密钥不匹配。

错误的密钥会导致如下错误或警告:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
@    
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 RSA host key has just been changed. 
The fingerprint for the RSA key sent by the remote host is 
38:c2:f6:0d:0d:49:d4:05:55:68:54:2a:2f:83:06:11. 
Please contact your system administrator. 
Add correct host key in /home/user/.ssh/known_hosts to get rid of this 
message. 
Offending key in /home/user/.ssh/known_hosts:12➊ 
RSA host key for host has changed and you have requested 
strict checking. 
Host key verification failed.

This usually just means that the remote host’s administrator changed the keys (this often happens when replacing hardware), but it never hurts to check with the administrator if you’re not sure. In any case, the preceding message tells you that the bad key is in line 12 of a user’s known_hosts file, as shown at ➊.

这通常只是表示远程主机的管理员更改了密钥(通常在更换硬件时会发生),但如果不确定,最好还是与管理员确认一下。

无论如何,前面的消息告诉您,有问题的密钥位于用户 known_hosts 文件的第12行,如图所示。

If you don’t suspect foul play, just remove the offending line or replace it with the correct public key.

如果您不怀疑有恶意操作,只需删除有问题的行或将其替换为正确的公钥。

SSH File Transfer Clients(SSH 文件传输客户端)

OpenSSH includes the file transfer programs scp and sftp, which are intended as replacements for the older, insecure programs rcp and ftp.

OpenSSH 包括文件传输程序 scp 和 sftp,这两个程序旨在取代较老、不安全的 rcp 和 ftp 程序。

You can use scp to transfer files to or from a remote machine to your machine or from one host to another. It works like the cp command. Here are a few examples:

您可以使用 scp 将文件从远程计算机传输到您的计算机,或者在两台主机之间传输文件。

它的工作方式类似于 cp 命令。以下是一些示例:

$ scp user@host:file . 
$ scp file user@host:dir 
$ scp user1@host1:file user2@host2:dir

The sftp program works like the command-line ftp client, using get and put commands. The remote host must have an sftp-server program installed, which you can expect if the remote host also uses OpenSSH.

sftp 程序类似于命令行 ftp 客户端,使用 get 和 put 命令。

远程主机必须安装 sftp-server 程序,如果远程主机也使用 OpenSSH,您可以期望这个程序已安装。

NOTE If you need more features and flexibility than the offerings of scp and sftp (for example, if you’re transferring large numbers of files often), have a look at rsync, described in Chapter 12.

注意:如果您需要比 scp 和 sftp 更多功能和灵活性的功能(例如,经常传输大量文件),请查看第 12 章中描述的 rsync。

SSH Clients for Non-Unix Platforms(非Unix平台的SSH客户端)

There are SSH clients for all popular operating systems, as listed on the OpenSSH web page (http://www.openssh.com/). Which one should you choose? PuTTY is a good, basic Windows client that includes a secure file-copy program. MacSSH works well for Mac OS 9.x and lower. Mac OS X is based on Unix and includes OpenSSH.

所有流行操作系统都有SSH客户端,可以在OpenSSH网页(http://www.openssh.com/)上找到相关信息。

你应该选择哪一个呢? PuTTY是一个不错的基础Windows客户端,包含一个安全的文件传输程序。

MacSSH适用于Mac OS 9.x及更低版本。

Mac OS X基于Unix,并包含OpenSSH。

10.4 The inetd and xinetd Daemons(inetd 和 xinetd 守护进程)

Implementing standalone servers for every service can be somewhat inefficient. Each server must be separately configured to handle port listening, access control, and port configuration. These actions are performed in the same way for most services; only when a server accepts a connection is there any difference in the way communication is handled.

为每个服务实现独立的服务器可能有些低效。每个服务器必须单独配置以处理端口监听、访问控制和端口配置。

对于大多数服务,这些操作都是以相同的方式执行的;只有当服务器接受连接时,通信处理方式才有所不同。

One traditional way to simplify the use of servers is with the inetd daemon, a kind of superserver designed to standardize network port access and interfaces between server programs and network ports. After you start inetd, it reads its configuration file and then listens on the network ports defined in that file. As new network connections come in, inetd attaches a newly started process to the connection.

简化服务器使用的一种传统方式是使用 inetd 守护进程,这是一种超级服务器,旨在标准化网络端口访问和服务器程序与网络端口之间的接口。

启动 inetd 后,它会读取其配置文件,然后监听该文件中定义的网络端口。随着新的网络连接到来,inetd 会将一个新启动的进程附加到连接上。

A newer version of inetd called xinetd offers easier configuration and better access control, but xinetd itself is being phased out in favor of systemd, which can provide the same functionality through socket units, as described in 6.4.7 systemd On-Demand and Resource-Parallelized Startup.

一个名为 xinetd 的更新版本提供了更简单的配置和更好的访问控制,但 xinetd 本身正在被 systemd 取代,后者可以通过套接字单元提供相同的功能,如 6.4.7 systemd 按需和资源并行化启动中所述。

Although inetd is no longer commonly used, its configuration shows everything necessary to set up a service. As it turns out, sshd can also be invoked by inetd rather than as a standalone server, as shown in this /etc/ inetd.conf configuration file:

尽管 inetd 不再常用,但其配置显示了设置服务所需的一切。

事实证明,sshd 也可以由 inetd 而不是作为独立服务器调用,如下所示在这个 /etc/ inetd.conf 配置文件中:

ident stream tcp  nowait root /usr/sbin/sshd sshd -i

The seven fields here are, from left to right:

o Service name. The service name from /etc/services (see 9.14.3 Port Numbers and /etc/services).
o Socket type. This is usually stream for TCP and dgram for UDP.
o Protocol. The transport protocol, usually tcp or udp.
o Datagram server behavior. For UDP, this is wait or nowait. Services using any other transport
protocol should use nowait.
o User. The username to run the service. Add .group to set a group.
o Executable. The program that inetd should connect to the service.
o Arguments. The arguments for the executable. The first argument should be the name of the program.

这里的七个字段依次是:

o 服务名称。来自 /etc/services 的服务名称(参见 9.14.3 端口号和 /etc/services)。
o 套接字类型。通常为 TCP 的流式(stream),UDP 的数据报式(dgram)。
o 协议。传输协议,通常为 tcp 或 udp。
o 数据报服务器行为。对于 UDP,为 wait 或 nowait。使用其他传输协议的服务应该使用 nowait。
o 用户。运行服务的用户名。添加 .group 以设置一个用户组。
o 可执行文件。inetd 应该连接到的程序。
o 参数。可执行文件的参数。第一个参数应该是程序的名称。

10.4.1 TCP Wrappers: tcpd, /etc/hosts.allow, and /etc/hosts.deny(TCP包装:tcpd、/etc/hosts.allow和/etc/hosts.deny)

Before lower-level firewalls became popular, many administrators used the TCP wrapper library and daemon for host control over network services. In these implementations, inetd runs the tcpd program, which first looks at the incoming connection as well as the access control lists in the /etc/hosts.allow and /etc/hosts.deny files. The tcpd program logs the connection, and if it decides that the incoming connection is okay, it hands it to the final service program. (Although you may find a system that still uses the TCP wrapper system, we won’t cover it in detail because it has largely fallen into disuse.)

在较低级别的防火墙变得流行之前,许多管理员使用TCP包装库和守护程序来控制网络服务的主机。

在这些实现中,inetd运行tcpd程序,该程序首先查看传入连接以及/etc/hosts.allow和/etc/hosts.deny文件中的访问控制列表。

tcpd程序记录连接,如果确定传入连接正常,则将其移交给最终的服务程序。

(尽管您可能会发现仍在使用TCP包装系统的系统,但我们不会详细介绍,因为它已经大部分被废弃。)

10.5 Diagnostic Tools(诊断工具)

Let’s look at a few diagnostic tools that are useful for poking around the application layer. Some dig into the transport and network layers, because everything in the application layer eventually maps down to something in those lower layers.

让我们看一些有用的诊断工具,用于查看应用层。

有些工具会深入到传输层和网络层,因为应用层中的所有内容最终都会映射到这些较低的层中的某些内容。

As discussed in Chapter 9, netstat is a basic network service debugging tool that can display a number of transport and network layer statistics. Table 10-2 reviews a few useful options for viewing connections.

如第9章所讨论的,netstat是一种基本的网络服务调试工具,可以显示许多传输层和网络层的统计信息。

表10-2列出了一些有用的选项,用于查看连接。

Table 10-2. Useful Connection-Reporting Options for netstat

表10-2. netstat的有用连接报告选项

image.png

10.5.1 lsof

In Chapter 8, you learned that lsof can track open files, but it can also list the programs currently using or listening to ports. For a complete list of programs using or listening to ports, run

在第8章中,您了解到 lsof 可以跟踪打开的文件,但它也可以列出当前正在使用或监听端口的程序。

要获取使用或监听端口的程序的完整列表,请运行

# lsof -i 

When run as a regular user, this command only shows that user’s processes. When run as root, the output should look something like this, displaying a variety of processes and users:

以普通用户身份运行此命令时,只会显示该用户的进程。

以 root 用户身份运行时,输出应该类似于以下内容,显示各种进程和用户:

image.png

This example output shows users and process IDs for server and client programs, from the old-style RPC services at the top, to the multicast DNS service provided by avahi, and even an IPv6-ready printer service (cupsd). The last two entries show client connections: an SSH connection and a secure web connection from the Chromium web browser. Because the output can be extensive, it’s usually best to apply a filter (as discussed in the following section).

这个示例输出显示了服务器和客户端程序的用户和进程ID,从顶部的旧式RPC服务,到由avahi提供的多播DNS服务,甚至是一个支持IPv6的打印机服务(cupsd)。

最后两个条目显示了客户端连接:一个SSH连接和来自Chromium网页浏览器的安全网页连接。

由于输出可能很庞大,通常最好应用过滤器(如下一节所讨论的)。

The lsof program is like netstat in that it tries to reverse-resolve every IP address that it finds into a hostname, which slows down the output. Use the -n option to disable name resolution:

lsof程序类似于netstat,它尝试将找到的每个IP地址反向解析为主机名,这会减慢输出速度。

使用-n选项来禁用名称解析:

# lsof -n -i 

You can also specify -P to disable /etc/services port name lookups.

您还可以指定-P选项来禁用/etc/services端口名称查找。

Filtering by Protocol and Port(按协议和端口过滤)

If you’re looking for a particular port (say, you know that a process is using a particular port and you want to know what that process is), use this command:

如果您正在寻找特定的端口(比如,您知道某个进程正在使用特定端口,想要知道该进程是什么),可以使用以下命令:

# lsof -i:port

The full syntax is as follows:

完整的语法如下:

# lsof -iprotocol@host:port 

The protocol, @host, and :port parameters are all optional and will filter the lsof output accordingly. As with most network utilities, host and port can be either names or numbers. For example, if you only want to see connections on TCP port 80 (the HTTP port), use

协议、@主机和:端口号参数都是可选的,将根据它们过滤lsof输出。

与大多数网络工具一样,主机和端口可以是名称或数字。

例如,如果您只想看到TCP端口80(HTTP端口)上的连接,请使用:

# lsof -iTCP:80

Filtering by Connection Status(通过连接状态过滤)

One particularly handy lsof filter is connection status. For example, to show only the processes listening on TCP ports, enter

连接状态是一个特别方便的 lsof 过滤器。

例如,要只显示监听 TCP 端口的进程,输入

# lsof -iTCP -sTCP:LISTEN

This command gives you a good overview of the network server processes currently running on your system. However, because UDP servers don’t listen and don’t have connections, you’ll have to use -iUDP to view running clients as well as servers. This usually isn’t a problem, because you probably won’t have many UDP servers on your system.

这个命令可以让你清楚地了解当前在你的系统上正在运行的网络服务器进程。

然而,由于UDP服务器不监听也不建立连接,你需要使用-iUDP选项来查看正在运行的客户端以及服务器。

通常情况下这不会是一个问题,因为你的系统上可能不会有很多UDP服务器。

10.5.2 tcpdump

If you need to see exactly what’s crossing your network, tcpdump puts your network interface card into promiscuous mode and reports on every packet that crosses the wire. Entering tcpdump with no arguments produces output like the following, which includes an ARP request and web connection:

如果你需要准确查看穿过你的网络的内容,tcpdump会将你的网络接口卡置于混杂模式,并报告每一个经过的数据包。

输入无参数的tcpdump会产生如下输出,其中包括一个ARP请求和web连接:

# tcpdump 
tcpdump: listening on eth0 
20:36:25.771304 arp who-has mikado.example.com tell duplex.example.com 
20:36:25.774729 arp reply mikado.example.com is-at 0:2:2d:b:ee:4e 
20:36:25.774796 duplex.example.com.48455 > mikado.example.com.www: S 
3200063165:3200063165(0) 
38815804[|tcp]> 
(DF) 
win 
5840 
<mss 
1460,sackOK,timestamp 
20:36:25.779283 mikado.example.com.www > duplex.example.com.48455: S 
ack 
3200063166 
win 
5792 
<mss 
3494716463:3494716463(0) 
1460,sackOK,timestamp 
4620[|tcp]> (DF) 
20:36:25.779409 duplex.example.com.48455 > mikado.example.com.www: . 
ack 1 win 
5840 <nop,nop,timestamp 38815805 4620> (DF) 
20:36:25.779787 duplex.example.com.48455 > mikado.example.com.www: P 
1:427(426) 
ack 1 win 5840 <nop,nop,timestamp 38815805 4620> (DF) 
20:36:25.784012 mikado.example.com.www > duplex.example.com.48455: . 
ack 427 
win 6432 <nop,nop,timestamp 4620 38815805> (DF) 
20:36:25.845645 mikado.example.com.www > duplex.example.com.48455: P 
1:773(772) 
ack 427 win 6432 <nop,nop,timestamp 4626 38815805> (DF) 
20:36:25.845732 duplex.example.com.48455 > mikado.example.com.www: . 
ack 773 
win 6948 <nop,nop,timestamp 38815812 4626> (DF) 
9 packets received by filter 
0 packets dropped by kernel

You can tell tcpdump to be more specific by adding filters. You can filter based on source and destination hosts, networks, Ethernet addresses, protocols at many different layers in the network model, and much more. Among the many packet protocols that tcpdump recognizes are ARP, RARP, ICMP, TCP, UDP, IP, IPv6, AppleTalk, and IPX packets. For example, to tell tcpdump to output only TCP packets, run

你可以通过添加过滤器来让tcpdump更具体。

你可以根据源主机、目标主机、网络、以太网地址、网络模型中的许多不同层面的协议等进行过滤,还有更多选项。

tcpdump能识别的许多数据包协议包括ARP、RARP、ICMP、TCP、UDP、IP、IPv6、AppleTalk和IPX数据包。

例如,要告诉tcpdump仅输出TCP数据包,可以运行:

# tcpdump tcp

To see web packets and UDP packets, enter

要查看网络数据包和 UDP 数据包,请输入

# tcpdump udp or port 80

NOTE If you need to do a lot of packet sniffing, consider using a GUI alternative to tcpdump such as Wireshark.

注意 如果需要进行大量数据包嗅探,可考虑使用图形用户界面来替代 tcpdump,如 Wireshark。

Primitives(基元)

In the preceding examples, tcp, udp, and port 80 are called primitives. The most important primitives are in Table 10-3:

在前面的示例中,tcp、udp 和端口 80 被称为基元。表 10-3 列出了最重要的基元:

Table 10-3. tcpdump Primitives

表 10-3. tcpdump 基元

Table 10-3. tcpdump Primitives

Operators(运算符)

The or used in the previous example is an operator. tcpdump can use multiple operators (such as and and !), and you can group operators in parentheses. If you plan to do any serious work with tcpdump, make sure to read the manual page, especially the section that describes the primitives.

在前面的示例中使用的 or 是一个运算符。tcpdump 可以使用多个运算符(比如 and 和 !),你可以将运算符分组在括号中。

如果你打算在 tcpdump 中进行任何严肃的工作,请务必阅读手册页,特别是描述基本操作的部分。

When Not to Use tcpdump(不应该使用 tcpdump 的情况)

Be very careful when using tcpdump. The tcpdump output shown earlier in this section includes only packet TCP (transport layer) and IP (Internet layer) header information, but you can also make tcpdump print the entire packet contents. Even though many network operators make it far too easy to look at their network packets, you shouldn’t snoop around on networks unless you own them.

在使用 tcpdump 时要非常小心。在本节中之前展示的 tcpdump 输出仅包含数据包的 TCP(传输层)和 IP(网络层)头部信息,但你也可以让 tcpdump 打印完整的数据包内容。

尽管许多网络运营商让查看他们的网络数据包变得非常容易,但你不应该在没有权限的情况下窥探网络。

10.5.3 netcat

If you need more flexibility in connecting to a remote host than a command like telnet host port allows, use netcat (or nc). netcat can connect to remote TCP/UDP ports, specify a local port, listen on ports, scan ports, redirect standard I/O to and from network connections, and more. To open a TCP connection to a port with netcat, run

如果您需要比telnet主机端口命令更灵活地连接到远程主机,可以使用netcat(或nc)。

netcat可以连接到远程TCP/UDP端口,指定本地端口,监听端口,扫描端口,重定向标准I/O到网络连接等等。

要使用netcat打开到端口的TCP连接,请运行

$ netcat host port 

netcat only terminates when the other side of the connection ends the connection, which can confuse things if you redirect standard input to netcat. You can end the connection at any time by pressing CTRL-C. (If you’d like the program and network connection to terminate based on the standard input stream, try the sock program instead.)

netcat 只有在连接的另一端结束连接时才会终止,如果你将标准输入重定向到 netcat,这可能会导致混淆。你可以通过按下 CTRL-C 随时结束连接。

(如果你希望程序和网络连接根据标准输入流终止,请尝试使用 sock 程序。)

To listen on a particular port, run

要监听特定端口,请运行

$ netcat -l -p port_number 

10.5.4 Port Scanning(端口扫描)

Sometimes you don’t even know what services the machines on your networks are offering or even which IP addresses are in use. The Network Mapper (Nmap) program scans all ports on a machine or network of machines looking for open ports, and it lists the ports it finds. Most distributions have an Nmap package, or you can get it at http://www.insecure.org/. (See the Nmap manual page and online resources for all that Nmap can do.)

有时候你甚至不知道你网络上的设备提供了哪些服务,甚至不知道哪些 IP 地址正在使用。

网络映射工具(Nmap)程序会扫描一台机器或一组机器上的所有端口,寻找开放的端口,并列出它所找到的端口。

大多数发行版都有 Nmap 软件包,或者你可以在 http://www.insecure.org/ 获取它。

(查看 Nmap 手册页和在线资源,了解 Nmap 的所有功能。)

When listing ports on your own machine, it often helps to run the Nmap scan from at least two points: from your own machine and from another one (possibly outside your local network). Doing so will give you an overview of what your firewall is blocking.

当列出自己机器上的端口时,通常最好从至少两个点运行 Nmap 扫描:从你自己的机器和另一个机器(可能是在本地网络之外的机器)。

这样做将让你了解你的防火墙正在阻止什么。

WARNING If someone else controls the network that you want to scan with Nmap, ask for permission. Network administrators watch for port scans and usually disable access to machines that run them.

警告 如果有其他人控制你想要用 Nmap 扫描的网络,请先征得许可。网络管理员会监视端口扫描,并通常会禁止运行它们的设备的访问。

Run nmap host to run a generic scan on a host. For example:

运行 nmap host 命令在主机上运行一次通用扫描。

例如:

$ nmap 10.1.2.2 
Starting Nmap 5.21 ( http://nmap.org ) at 2015-09-21 16:51 PST 
Nmap scan report for 10.1.2.2 
Host is up (0.00027s latency). 
Not shown: 993 closed ports 
PORT     
STATE SERVICE 
22/tcp   open  ssh 
25/tcp   open  smtp 
80/tcp   open  http 
111/tcp  open  rpcbind 
8800/tcp open  unknown 
9000/tcp open  cslistener 
9090/tcp open  zeus-admin 
Nmap done: 1 IP address (1 host up) scanned in 0.12 seconds

As you can see, a number of services are open here, many of which are not enabled by default on most distributions. In fact, the only one here that’s usually on by default is port 111, the rpcbind port.

正如您所见,这里打开了许多服务,其中许多在大多数发行版上默认情况下都未启用。实际上,这里通常默认启用的仅有一个,即端口111,即rpcbind端口。

10.6 Remote Procedure Call (RPC)

What about the rpcbind service that you just saw in the scan in the preceding section? RPC stands for remote procedure call, a system residing in the lower parts of the application layer. It’s designed to make it easier for programmers to access network applications by leveraging the fact that programs call functions on remote programs (identified by program numbers) and the remote programs return a result code or message.

你刚刚在前面的扫描中看到的rpcbind服务怎么样?RPC代表远程过程调用,是位于应用层较低部分的系统。它旨在通过利用程序调用远程程序(由程序号标识)并远程程序返回结果代码或消息的方式,使程序员更容易访问网络应用程序。

RPC implementations use transport protocols such as TCP and UDP, and they require a special intermediary service to map program numbers to TCP and UDP ports. The server is called rpcbind, and it must be running on any machine that wants to use RPC services.

RPC实现使用诸如TCP和UDP之类的传输协议,并且它们需要一个特殊的中间服务来将程序号映射到TCP和UDP端口。该服务器称为rpcbind,任何想要使用RPC服务的机器都必须运行该服务。

To see what RPC services your computer has, run

要查看你的计算机具有哪些RPC服务,运行以下命令:

$ rpcinfo -p localhost 

RPC is one of those protocols that just doesn’t want to die. The Network File System (NFS) and Network Information Service (NIS) systems use RPC, but they are completely unnecessary on standalone machines. But whenever you think that you’ve eliminated all need for rpcbind, something else comes up, such as File Access Monitor (FAM) support in GNOME.

RPC是那种似乎不愿消亡的协议之一。

网络文件系统(NFS)和网络信息服务(NIS)系统使用RPC,但在独立机器上完全是不必要的。

但是,每当您认为已经消除了对rpcbind的所有需求时,又会出现其他问题,比如GNOME中的文件访问监视器(FAM)支持。

10.7 Network Security(网络安全)

Because Linux is a very popular Unix flavor on the PC platform, and especially because it is widely used for web servers, it attracts many unpleasant characters who try to break into computer systems. 9.21 Firewalls discussed firewalls, but that’s not really the whole story on security.

由于Linux是PC平台上非常流行的Unix版本,特别是因为它广泛用于Web服务器,吸引了许多不怀好意的人物试图侵入计算机系统。9.21 防火墙讨论了防火墙,但这并不是安全的全部故事。

Network security attracts extremists—those who really like to break into systems (whether for fun or money) and those who come up with elaborate protection schemes who really like to swat away people trying to break into their systems. (This, too, can be very profitable.) Fortunately, you don’t need to know very much to keep your system safe. Here are a few basic rules of thumb:

网络安全吸引了极端分子——那些真的喜欢入侵系统的人(无论是为了乐趣还是金钱),以及那些设计复杂保护方案的人,他们真的喜欢击退试图入侵他们系统的人。

(这也可以非常有利可图。)幸运的是,你不需要了解太多就能保护好你的系统。以下是一些基本的经验法则:

o Run as few services as possible. Intruders can’t break into services that don’t exist on your system. If you know what a service is and you’re not using it, don’t turn it on for the sole reason that you might want to use it “at some later point.”

  • 尽可能运行尽可能少的服务。入侵者无法入侵你系统上不存在的服务。如果你知道一个服务是什么,而你又没有使用它,不要仅仅因为你可能想在“以后的某个时候”使用它而打开它。

o Block as much as possible with a firewall. Unix systems have a number of internal services that you may not know about (such as TCP port 111 for the RPC port-mapping server), and no other system in the world should know about them. It can be very difficult to track and regulate the services on your system because many different kinds of programs listen on various ports. To keep intruders from discovering internal services on your system, use effective firewall rules, and install a firewall at your router.

  • 尽可能使用防火墙阻止一切。Unix系统有许多内部服务,你可能不知道它们的存在(比如TCP端口111用于RPC端口映射服务器),世界上没有其他系统应该知道它们。

    • 要跟踪和管理系统上的服务可能非常困难,因为许多不同种类的程序会监听各种端口。
    • 为了防止入侵者发现你系统上的内部服务,使用有效的防火墙规则,在你的路由器上安装一个防火墙。

o Track the services that you offer to the Internet. If you run an SSH server, Postfix, or similar services, keep your software up-to-date and get appropriate security alerts. (See 10.7.2 Security Resources for some online resources.)

  • 跟踪你向互联网提供的服务。如果你运行SSH服务器、Postfix或类似的服务,请保持软件更新,并获取适当的安全警报。(参见10.7.2 安全资源,了解一些在线资源。)

o Use “long-term support” distribution releases for servers. Security teams normally concentrate their work on stable, supported distribution releases. Development and testing releases such Debian Unstable and Fedora Rawhide receive much less attention.

  • 对于服务器,使用“长期支持”发行版。安全团队通常会集中精力在稳定、受支持的发行版上进行工作。开发和测试发行版如Debian Unstable和Fedora Rawhide接受的关注要少得多。

o Don’t give an account on your system to anyone who doesn’t need one. It’s much easier to gain superuser access from a local account than it is to break in remotely. In fact, given the huge base of software (and the resulting bugs and design flaws) available on most systems, it can be easy to gain superuser access to a system after you get to a shell prompt. Don’t assume that your friends know how to protect their passwords (or choose good passwords in the first place).

  • 不要为不需要的人在你的系统上创建账户。

    • 从本地账户获取超级用户权限比远程入侵要容易得多。
    • 事实上,鉴于大多数系统上可用的软件(以及由此产生的漏洞和设计缺陷),一旦你进入一个shell提示符,很容易获得系统的超级用户权限。
    • 不要假设你的朋友知道如何保护他们的密码(或者一开始就选择好密码)。

o Avoid installing dubious binary packages. They can contain Trojan horses. That’s the practical end of protecting yourself. But why is it important to do so? There are three basic kinds of network attacks:

  • 避免安装可疑的二进制软件包。它们可能包含特洛伊木马。

    • 这是保护自己的实际结束。但为什么这么做很重要呢?网络攻击有三种基本类型:

o Full compromise. This means getting superuser access (full control) of a machine. An intruder can accomplish this by trying a service attack, such as a buffer overflow exploit, or by taking over a poorly protected user account and then trying to exploit a poorly written setuid program.

  • 完全破坏。这意味着获得对机器的超级用户权限(完全控制)。

    • 入侵者可以通过尝试服务攻击,比如缓冲区溢出攻击,或者接管一个保护不力的用户账户,然后尝试利用一个编写不好的setuid程序来实现这一点。

o Denial-of-service (DoS) attack. This prevents a machine from carrying out its network services or forces a computer to malfunction in some other way without the use of any special access. These attacks are harder to prevent, but they are easier to respond to.

  • 拒绝服务(DoS)攻击。这会阻止机器执行其网络服务,或者以其他方式迫使计算机发生故障,而无需使用任何特殊访问。

    • 这些攻击更难预防,但更容易应对。

o Malware. Linux users are mostly immune to malware such as email worms and viruses, simply because their email clients aren’t stupid enough to actually run programs that they get in message attachments. But Linux malware does exist. Avoid downloading and installing binary software from places that you’ve never heard of.

  • 恶意软件。Linux用户大多免疫于恶意软件,如电子邮件蠕虫和病毒,仅仅因为他们的电子邮件客户端并不愚蠢到实际运行他们在消息附件中收到的程序。

    • 但Linux上确实存在恶意软件。避免从你从未听说过的地方下载和安装二进制软件。

    10.7.1 Typical Vulnerabilities

There are two important kinds of vulnerabilities to worry about: direct attacks and clear-text password sniffing. Direct attacks try to take over a machine without being terribly subtle. The most common is a buffer overflow exploit, where a careless programmer doesn’t check the bounds of a buffer array. The attacker fabricates a stack frame inside a huge chunk of data, dumps it to the remote server, and then hopes that the server overwrites its program data and eventually executes the new stack frame. Although a somewhat complicated attack, it’s easy to replicate.

有两种重要的漏洞需要担心:直接攻击和明文密码嗅探。直接攻击试图接管机器而不太敏锐。

最常见的是缓冲区溢出利用,一个粗心的程序员没有检查缓冲区数组的边界。

攻击者在大量数据中制造一个栈帧,将其转储到远程服务器,然后希望服务器覆盖其程序数据并最终执行新的栈帧。

虽然这是一个有些复杂的攻击,但很容易复制。

A second attack to worry about is one that captures passwords sent across the wire as clear text. As soon as an attacker gets your password, it’s game over. From there, the assailant will inevitably try to gain superuser access locally (which is much easier than making a remote attack), try to use the machine as an intermediary for attacking other hosts, or both.

第二种需要担心的攻击是捕获明文传输的密码。

一旦攻击者获取到你的密码,游戏就结束了。

从那里开始,攻击者将不可避免地尝试在本地获得超级用户访问权限(比进行远程攻击容易得多),尝试使用该机器作为攻击其他主机的中介,或两者兼而有之。

NOTE If you have a service that offers no native support for encryption, try Stunnel ( http://www.stunnel.org/), an encryption wrapper package much like TCP wrappers. Like tcpd, Stunnel is especially good at wrapping inetd services.

注意:如果您有一个不支持加密的服务,请尝试使用 Stunnel(http://www.stunnel.org/),这是一个类似于 TCP wrappers 的加密包装程序。与 tcpd 一样,Stunnel 尤其擅长包装 inetd 服务。

Some services are chronic attack targets due to poor implementation and design. You should always deactivate the following services (they’re rarely activated by default on most systems):

由于实施和设计不当,有些服务长期成为攻击目标。

应始终停用以下服务(大多数系统默认情况下很少激活这些服务):

  • ftpd For whatever reason, all FTP servers seem plagued with vulnerabilities. In addition, most FTP servers use clear-text passwords. If you have to move files from one machine to another, consider an SSH based solution or an rsync server.
  • telnetd, rlogind, rexecd All of these pass remote session data (including passwords) in clear-text form. Avoid them unless you happen to have a Kerberos-enabled version.
  • fingerd Intruders can get user lists and other information with the finger service.
  • ftpd 由于某种原因,所有 FTP 服务器似乎都深受漏洞困扰。此外,大多数 FTP 服务器使用明文密码。

    • 如果您必须从一台机器移动文件到另一台机器,请考虑使用基于 SSH 的解决方案或一个 rsync 服务器。
  • telnetd、rlogind、rexecd 所有这些服务以明文形式传递远程会话数据(包括密码)。

    • 除非您碰巧有一个启用了 Kerberos 的版本,否则应避免使用它们。
  • fingerd 入侵者可以通过 finger 服务获取用户列表和其他信息。

    10.7.2 Security Resources

Here are three good security sites:
o http://www.sans.org/ Offers training, services, a free weekly newsletter listing the top current vulnerabilities, sample security policies, and more.
o http://www.cert.org/ A place to look for the most severe problems.
o http://www.insecure.org/ This is the place to go for Nmap and pointers to all sorts of network exploittesting tools. It’s much more open and specific about exploits than are many other sites.

这里有三个优秀的网络安全网站:

  • http://www.sans.org/ 提供培训、服务、免费每周简报列出当前顶级漏洞、示例安全策略等。
  • http://www.cert.org/ 是寻找最严重问题的地方。
  • http://www.insecure.org/ 这是一个获取Nmap和各种网络漏洞测试工具指针的地方。它比许多其他网站更加开放和具体关于漏洞利用。

If you’re interested in network security, you should learn all about Transport Layer Security (TLS) and its predecessor, Secure Socket Layer (SSL). These user-space network levels are typically added to networking clients and servers to support network transactions through the use of public-key encryption and certificates. A good guide is Davies’s Implementing SSL/TLS Using Cryptography and PKI (Wiley, 2011).

如果你对网络安全感兴趣,你应该全面了解传输层安全性(TLS)及其前身安全套接字层(SSL)。

这些用户空间网络层通常添加到网络客户端和服务器中,通过公钥加密和证书支持网络交易。

一个好的指南是戴维斯(Davies)的《使用密码学和PKI实现SSL/TLS》(Wiley,2011年)。

10.8 Looking Forward(展望未来)

If you’re interested in getting your hands dirty with some complicated network servers, two very common ones are the Apache web server and the Postfix email server. In particular, Apache is easy to install and most distributions supply a package. If your machine is behind a firewall or NAT-enabled router, you can experiment with the configuration as much as you’d like without worrying about security.

如果你对涉足一些复杂的网络服务器感兴趣,那么两个非常常见的服务器是Apache Web服务器和Postfix邮件服务器。

特别是,Apache很容易安装,大多数发行版都提供了相关软件包。

如果你的机器位于防火墙或启用NAT的路由器后面,你可以随意尝试不用担心安全性的配置。

Throughout the last few chapters, we’ve been gradually moving from kernel space into user space. Only a few utilities discussed in this chapter, such as tcpdump, interact with the kernel. The remainder of this chapter describes how sockets bridge the gap between the kernel’s transport layer and the user-space application layer. It’s more advanced material, of particular interest to programmers, so feel free to skip to the next chapter if you like.

在过去的几章中,我们逐渐从内核空间移动到用户空间。

本章仅讨论了几个与内核交互的实用工具,比如tcpdump。

本章的其余部分描述了套接字如何弥合内核的传输层和用户空间应用层之间的差距。

这是更加高级的内容,特别适合程序员,如果你愿意,可以随意跳到下一章。

10.9 Sockets: How Processes Communicate with the Network(套接字:进程如何与网络通信)

We’re now going to shift gears a little and look at how processes do the work of reading data from and writing data to the network. It’s easy enough for processes to read from and write to network connections that are already set up: All you need are some system calls, which you can read about in the recv(2) and send(2) manual pages. From the point of view of a process, perhaps the most important thing to know is how to refer to the network when using these system calls. On Unix systems, a process uses a socket to identify when and how it’s talking to the network. Sockets are the interface that processes use to access the network through the kernel; they represent the boundary between user space and kernel space. They’re often also used for interprocess communication (IPC).

现在我们将稍作转变,看看进程如何从网络读取数据和向网络写入数据。

对于进程来说,从已经建立好的网络连接中读取数据和写入数据是相当容易的:你只需要一些系统调用,你可以在 recv(2) 和 send(2) 的手册页面中找到相关信息。

从进程的角度来看,也许最重要的是在使用这些系统调用时如何引用网络。

在Unix系统中,进程使用套接字来识别它何时以及如何与网络通信。

套接字是进程通过内核访问网络的接口;它们代表了用户空间和内核空间之间的边界。

它们经常也被用于进程间通信(IPC)。

There are different types of sockets because processes need to access the network in different ways. For example, TCP connections are represented by stream sockets (SOCK_STREAM, from a programmer’s point of view), and UDP connections are represented by datagram sockets (SOCK_DGRAM).

由于进程需要以不同的方式访问网络,因此存在不同类型的套接字。

例如,TCP连接由流套接字(SOCK_STREAM,从程序员的角度看)表示,而UDP连接由数据报套接字(SOCK_DGRAM)表示。

Setting up a network socket can be somewhat complicated because you need to account for socket type, IP addresses, ports, and transport protocol at particular times. However, after all of the initial details are sorted out, servers use certain standard methods to deal with incoming traffic from the network.

设置网络套接字可能会有些复杂,因为您需要考虑套接字类型、IP地址、端口和特定时间的传输协议。

然而,一旦所有初始细节都得到解决,服务器就会使用某些标准方法来处理来自网络的传入流量。

The flowchart in Figure 10-1 shows how many servers handle connections for incoming stream sockets. Notice that this type of server involves two kinds of sockets: a listening socket and a socket for reading and writing. The master process uses the listening socket to look for connections from the network. When a new connection comes in, the master process uses the accept() system call to accept the connection, which creates the read/write socket dedicated to that one connection. Next, the master process uses fork() to create a new child process to deal with the connection. Finally, the original socket remains the listener and continues to look for more connections on behalf of the master process.

图 10-1 中的流程图显示了许多服务器如何处理输入流套接字的连接。

请注意,这种服务器涉及两种套接字:监听套接字和用于读写的套接字。

主进程使用监听套接字查找来自网络的连接。

当有新的连接进来时,主进程会使用 accept() 系统调用来接受该连接,从而创建专用于该连接的读写套接字。

接着,主进程使用 fork() 创建一个新的子进程来处理该连接。

最后,原始套接字仍作为监听器,继续代表主进程寻找更多连接。

After a process has set up a socket of a particular type, it can interact with it in a way that fits the socket type. This is what makes sockets flexible: If you need to change the underlying transport layer, you don’t have to rewrite all of the parts that send and receive data; you mostly need to modify the initialization code.

在一个进程建立了特定类型的套接字之后,它可以以适合套接字类型的方式与之交互。

这就是套接字灵活的原因:如果你需要更改底层传输层,你不必重写所有发送和接收数据的部分;

你只需修改初始化代码即可。

image.png

Figure 10-1. One method for accepting and processing incoming connections

图10-1. 一种接受和处理传入连接的方法

If you’re a programmer and you’d like to learn how to use the socket interface, Unix Network Programming, Volume 1, 3rd edition, by W. Richard Stephens, Bill Fenner, and Andrew M. Rudoff (Addison-Wesley Professional, 2003) is the classic guide. Volume 2 also covers interprocess communication.

如果您是一名程序员,想学习如何使用套接字接口,那么《Unix网络编程》第1卷,第3版,作者W. Richard Stephens、Bill Fenner和Andrew M. Rudoff(Addison-Wesley Professional,2003年)是经典指南。

第2卷也涵盖了进程间通信。

10.10 Unix Domain Sockets(Unix 域套接字)

Applications that use network facilities don’t have to involve two separate hosts. Many applications are built as client-server or peer-to-peer mechanisms, where processes running the same machine use interprocess communication (IPC) to negotiate what work needs to be done and who does it. For example, recall that daemons such as systemd and NetworkManager use D-Bus to monitor and react to system events.

使用网络设施的应用程序不一定要涉及两个独立的主机。

许多应用程序被构建为客户端-服务器或对等机制,其中在同一台计算机上运行的进程使用进程间通信(IPC)来协商需要执行什么工作以及由谁执行。

例如,诸如 systemd 和 NetworkManager 等守护进程使用 D-Bus 监控并响应系统事件。

Processes can use regular IP networking over localhost (127.0.0.1) to communicate, but instead, typically use a special kind of socket, which we briefly touched upon in Chapter 3, called a Unix domain socket. When a process connects to a Unix domain socket, it behaves almost exactly like a network socket: It can listen for and accept connections on the socket, and you can even choose between different kinds of socket types to make it behave like TCP or UDP.

进程可以通过本地主机(127.0.0.1)上的常规 IP 网络进行通信,但通常会使用一种特殊类型的套接字,我们在第 3 章中简要介绍过,称为 Unix 域套接字

当一个进程连接到一个 Unix 域套接字时,它几乎与网络套接字的行为完全相同:它可以在套接字上监听并接受连接,甚至可以选择不同类型的套接字来使其表现得像 TCP 或 UDP 一样。

NOTE It’s important to remember that a Unix domain socket is not a network socket, and there’s no network behind one. You don’t even need networking to be configured to use one. And Unix domain sockets don’t have to be bound to socket files. A process can create an unnamed Unix domain socket and share the address with another process.

注意 重要的是要记住 Unix 域套接字不是网络套接字,它背后没有网络。甚至不需要配置网络就可以使用它。

而且 Unix 域套接字不必绑定到套接字文件上。

一个进程可以创建一个未命名的 Unix 域套接字,并与另一个进程共享地址。

10.10.1 Advantages for Developers(开发者的优势)

Developers like Unix domain sockets for IPC for two reasons. First, they allow developers the option to use special socket files in the filesystem to control access, so any process that doesn’t have access to a socket file can’t use it. And because there’s no interaction with the network, it’s simpler and less prone to conventional network intrusion. For example, you’ll usually find the socket file for D-Bus in /var/run/dbus:

开发者喜欢使用 Unix 域套接字进行进程间通信有两个原因。

首先,它们允许开发者使用文件系统中的特殊套接字文件来控制访问权限,因此任何没有访问权限的进程都无法使用它。

而且由于不涉及网络交互,这样做更简单,且不容易受到传统网络入侵的影响。

例如,通常你会在 /var/run/dbus 目录下找到 D-Bus 的套接字文件:

$ ls -l /var/run/dbus/system_bus_socket 
srwxrwxrwx 1 root root 0 Nov 9 08:52 /var/run/dbus/system_bus_socket

Second, because the Linux kernel does not have to go through the many layers of its networking subsystem when working with Unix domain sockets, performance tends to be much better.

第二,由于Linux内核在使用Unix域套接字时无需经过许多层网络子系统,因此性能往往更好。

Writing code for Unix domain sockets is not much different from supporting normal network sockets. Because the benefits can be significant, some network servers offer communication through both network and Unix domain sockets. For example, the MySQL database server mysqld can accept client connections from remote hosts, but it usually also offers a Unix domain socket at /var/run/mysqld/mysqld.sock.

编写Unix域套接字的代码与支持普通网络套接字并无太大不同。

由于好处可能非常显著,一些网络服务器提供通过网络和Unix域套接字进行通信的功能。

例如,MySQL数据库服务器mysqld可以接受来自远程主机的客户端连接,但通常也提供位于/var/run/mysqld/mysqld.sock的Unix域套接字。

10.10.2 Listing Unix Domain Sockets(列出 Unix 域套接字)

You can view a list of Unix domain sockets currently in use on your system with lsof -U:

您可以使用命令 lsof -U 查看当前系统上正在使用的 Unix 域套接字列表:

# lsof -U 

COMMAND mysqld PID 19701 USER mysql /var/run/mysqld/mysqld.sock chromium- socket tlsmgr socket tlsmgr 26534 juser 30480 postfix FD 30480 postfix TYPE DEVICE SIZE/OFF 12u unix 0xe4defcc0 5u 5u 6u unix 0xeeac9b00 unix 0xc3384240 unix 0xe20161c0 NODE NAME 0t0 35201227 0t0 42445141 0t0 17009106 0t0 10965 private/tlsmgr

--snip--

The listing will be quite long because many modern applications make extensive use of unnamed sockets. You can identify the unnamed ones because you’ll see socket in the NAME output column.

由于许多现代应用程序广泛使用未命名套接字,因此清单将会相当长。

您可以通过在“NAME”输出列中看到套接字来识别未命名套接字。


Xander
195 声望50 粉丝