StupidBeauty
Read times:1508Posted at: - no title specified

netcat文档翻译:网络猫 – 从此网络连接轻而易举,Netcat – network connections made easy

原文: http://www.stearns.org/doc/nc-intro.current.html

在我创建了那些终端脚本中,有一大部分都会将一个命令的输出通过管道输入到另一个命令,例如:

$ cat /var/log/messages | awk '{print $4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15}' | sed -e 's/\[[0-9]*\]:/:/' | sort | uniq | less

它会显示出做了以下处理之后的系统日志文件:去除时间戳,去除[12345]这样的进程编号,去除重复项(1000条整洁的、排序过的、唯一的日志行,比6000 条混乱的日志行要容易阅读得多)

如果所有的处理都可以在同一台机器上完成的话,则,以上技术狠好用。假如我想将这些数据通过管道发送到另一台机器上呢?例如,我不想使用这台机器上的less来查看这些日志,而是想将输出内容发送到我的笔记本电脑,再用笔记本电脑来查看它。理想情况下,对应的命令可能会是这样的:

$ cat /var/log/messages | awk '{print $4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15}' | sed -e 's/\[[0-9]*\]:/:/' | sort | uniq | laptop

这样的语法是不起作用的,因为,终端脚本会认为自己应当将数据传递给一个叫做laptop 的 程序 ——这个程序并不存在。然而,还是有办法的。

初识Netcat

Netcat5年前编写的,正是用来实现这种神奇的功能——使得用户无需编程就能够在不同机器之间建立网络连接。让我们来看一些用法示例。

假设,我遇到一个有问题的网页服务器,它并未返回我所想要的内容。我想知道,对于某个特定的请求,它回复的 究竟 是什么:

echo -e "GET http://mason.stearns.org HTTP/1.0\n\n" | nc mason.stearns.org 80 | less

以下是我通过less 看到的结果:

HTTP/1.1 200 OK

Date: Sun, 12 Nov 2000 22:56:42 GMT

Server: Apache/1.3.3 (Unix)  (Red Hat/Linux)

Last-Modified: Thu, 26 Oct 2000 05:13:45 GMT

ETag: "15941-577c-39f7bd89"

Accept-Ranges: bytes

Content-Length: 22396

Connection: close

Content-Type: text/html

<html>

<head>

<title>Mason - the automated firewall builder for Linux</title>

<META NAME="keywords" CONTENT="firewall, Linux, packet, filter, ipfwadm, ipchains, automated, rules, iptables, netfilter, builder">

</head>

<body>

<center><img src="mason-banner.gif"></center>

...

echo命令为我创建了一个HTTP请求。HTTP协议要求在请求的末尾带上两个换行符,所以我用了两个\n来创建它们。实际的netcat命令(nc)会从标准输入流(stdin)读取到这个请求。我所使用的命令行参数("mason.stearns.org 80")告诉netcat要连接到服务器上的80 端口,然后发送"GET http..."命令。然后,Netcat监听回复(网页以及所有的协议头)并且将其内容传递给less命令。妳可以从下图中理解netcat的工作方式:

Web Server

^   |

|   v

^   |

|   v

echo --> netcat --> less

向上指向"Web"的那个箭头,表示向外发出的网页请求,而从server 向下指的那个箭头,表示返回的网页。

现在,我可以查看从服务器返回的具体html内容,这样就可以仔细研究在这个html 请求中发生了什么。

妳自己的服务器——无需编程!

我们已经见识了,netcat可以用作一个tcp/ip客户端程序,使得我们可以连接到一个远程服务器,向它发送一个请求,然后将回复的内容传递给别的程序。它还可以用作一个服务器。

我想要建立一个简单的服务器,用来报告我编写的Mason 软件的稳定版及开发版。我希望它运行于mason.stearns.org 的1500 端口。我还希望无需再编写另一个软件来完成这个工作。尽管我可以将这个信息放置在某个可被finger 访问的文件中,但是,我不倾向于运行finger服务器,因为,那存在着安全性和隐私性方面的隐患。首先,我创建一个文件,其中记录着我想要分享的信息:

<pre>                                                                                                                                                        

The latest versions of Mason are:                                                                                                                                    

STABLE: 0.13.0                                                                                                                                                      

DEVELOPMENT: 0.13.9.3                                                                                                                                                

</pre>                                                                                                                                                              

为什么使用<pre>标记?我希望这砣信息可以同时被netcat客户端和网页浏览器访问到。如果我省掉<pre>标记,则,网页浏览器会将所有内容显示在同一行。好了,现在,我们告知服务器,当有客户端连接上来的时候,就发送这个文件的内容:

while true ; do cat /home/wstearns/mason-version  | nc -l -p 1500 | head --bytes 2000 >>/tmp/requests ; date >>/tmp/requests ; done

"while true; do....done"会在一个无限循环中运行这个命令。因为netcat在发送了单个文件之后立即退出,所以,这段脚本又会立即再次启动netcat,于是又可以接受下次请求了。

"cat"将版本信息文件的内容传递给netcat;这就是我想要回复给用户的文本内容。

"nc -l -p 1500"告知netcat要监听( listen)端口( port 1500 。一旦它在1500 端口上接收了一个连接,就会将mason-version 文本内容发送到远程的客户端。客户端发送的请求内容中,前面最多2000个字节的内容会被追加到/tmp/requests文件中,然后再追加该请求的时间戳。这就提供了一个简单的日志功能,同时可以避免某个坏蛋向那个端口发送几G的数据以至于塞满了/tmp所在的硬盘。

在客户端机器上,我可以连接到这个服务器,以查看Mason 的最新版本信息:

[wstearns@sparrow wstearns]$ nc localhost 1500

<pre>

The latest versions of Mason are:

STABLE: 0.13.0

DEVELOPMENT: 0.13.9.3

</pre>

[wstearns@sparrow wstearns]$

当客户端收到回复内容的时候, /tmp/requests 中就会包含有 "Sun Nov 12 18:33:01 EST 2000" 我还可以用浏览器来查看这个数据,只需要打开 http://mason.stearns.org:1500 就行了。 在浏览器中看,除了<pre>标记不见了之外,其它内容都是相同的。 妳还可以使用 "telnet mason.stearns.org 1500" 它返回的内容会与"nc localhost 1500"相同。

日志文件中记录了网页浏览器发送的协议头内容:

GET / HTTP/1.0

User-Agent: Mozilla/4.75 [en] (X11; U; Linux 2.4.0-test11 i686)

Pragma: no-cache

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*

Accept-Encoding: gzip

Accept-Language: en

Accept-Charset: iso-8859-1,*,utf-8

Via: 1.0 sparrow.websense.net:3128 (Squid/2.3.STABLE4)

X-Forwarded-For: 127.0.0.1

Host: 127.0.0.1:1500

Cache-Control: max-age=259200

Connection: keep-alive

Sun Nov 12 18:39:47 EST 2000

对于创建一个真正的服务器,只剩下最后一条细节事项了。我希望它在启动阶段就运行起来,并且以非root用户来运行。以下是要向/etc/rc.d/rc.local中添加的代码行:

nohup su nobody -c 'while true ; do cat /home/wstearns/mason-version  | nc -l -p 1500 | head --bytes 2000 >>/tmp/requests ; date >>/tmp/requests ; done' &

/home/wstearns/mason-version替换成妳想要显示的文件,将/tmp/requests替换成妳想要使用的日志文件,于是,妳就拥有了一个立即可用的服务器,可用来显示任意数据。如果妳不想要日志功能,那么,将">>/tmp/requests"替换">>/dev/null",并且删除"; date >>/tmp/requests"就可以了。

一个通用的tcp代理

netcat 还有一个非常有趣的用途,在调试网络通信内容时非常有用。还记得我们的第一个示例吗?我们想要看到远程服务器回复的详细内容。那么,如果我们想要看人们向我们的某个服务器发送的所有请求,并且想要看服务器回复给他/她们的内容,怎么做呢?其实这并不难。

让我们来监视mason.stearns.org 上的网页服务器。首先,我们要告诉这个服务器监听另一个端口,例如81。具体做法就是,编辑"/etc/httpd/httpd.conf",将"Listen 80"改成"Listen 127.0.0.1:81",然后重启网页服务器。

现在,我们启动一个netcat服务器,监听80 端口。我们还会启动一个netcat客户端,与工作于81 端口的真正网页服务器通信。让它们将自己接收到的数据互相传递给对方,这样,它们就组成了一个 代理 ;即为某个插入到网络连接中间的东西。以下是我们使用的命令:

mknod backpipe p

nc -l -p 80 0<backpipe | tee -a inflow | nc localhost 81 | tee -a outflow 1>backpipe

因为bash的管道只会向一个方向传递数据,所以,我们还需要提供一种手段来传递回复数据。我们可以使用mknod 命令来在本地文件系统上创建一个管道,以传递反方向的数据;这个命令只需要执行一次。

从客户端向此代理发起的请求,首先来到监听于80 端口的第一个nc命令。它们被传递给"tee"命令,该命令会将它们记录到inflow文件中,然后被传递给第二个nc命令,它会将这些数据传递给真正的网页服务器。当服务器回复了数据的时候,首先到达第二个nc命令,被第二个tee命令记录outflow文件中,然后被推送到本地文件系统上的backpipe 管道中。由于第一个netcat就在监听那个管道,所以,这些回复内容被传递给第一个netcat,然后它就将这些内容回复给原始的客户端。

nc-tee-nc-tee 命令的具体形式,取决于多种因素:妳是想要手动启动它们,还是想要在一个开机脚本中启动它们;妳想要它们自动重新启动,还是只想监听某个单个连接。妳可以写一个跟前文中的"nohup su nobody -c 'while...done' & 类似的脚本,这样就产生了一个可通过开机脚本启动的持久代理,但是,可能需要做点小调整。

尽管上面这个示例是用来监视网页服务器的tcp数据流的,但是,以上技巧可以用来监视任意的tcp连接。实际上,由于nc也支持udp数据包——这是telnet做不到的——因此,甚至应当能够用类似的手段来创建udp代理

Your opinions

Your name:Email:Website url:Opinion content:
- no title specified

HxLauncher: Launch Android applications by voice commands