请收好Netcat网络工具中的瑞士军刀,从此故障诊断不用愁!

Netcat 号称 TCP/IP 的瑞士军刀并非浪得虚名 , 以体积小(可执行 200KB)功能灵活而著称 , 在各大发行版中都默认安装 , 你可以用它来做很多网络相关的工作 , 熟练使用它可以不依靠其他工具做一些很有用的事情 。
最初作者是叫做“霍比特人”的网友 Hobbit hobbit@avian.org 于 1995 年在 UNIX 上以源代码的形式发布 , Posix 版本的 netcat 主要有 GNU 版本的 netcat 和 OpenBSD 的 netcat 两者都可以在 debian/ubuntu 下面安装 , 但是 windows 下面只有 GNU 版本的 port 。
不管是程序员还是运维 , 熟悉这个命令都可以让很多工作事半功倍 , 然而网上基本 90% 的 netcat 文章说的都是老版本的 OpenBSD 的 netcat , 已经没法在主流 linux 上使用了 , 所以我们先要检查版本:
在 debian/ubuntu 下面:
readlink -f $(which nc)
看看 , 结果会有两种:

  • /bin/nc.traditional: 默认 GNU 基础版本 , 一般系统自带 。
  • /bin/nc.openbsd: openbsd 版本 , 强大很多 。
都可以用 apt-get install nc-traditional 或者 apt-get install nc-openbsd 来选择安装 。不管是 GNU 版本还是 OpenBSD 版本 , 都有新老的区别 , 主要是传送文件时 stdin 发生 EOF 了 , 老版本会自动断开 , 而新的 gnu/openbsd 还会一直连着 , 两年前 debian jessie 时统一升过级 , 导致网上的所有教程几乎同时失效 。
下面主要以最新的 GNU 版本为主同时对照更强大的 openbsd 版本进行说明 。
端口测试
你在服务器 A主机(192.168.1.2) 上面 8080 端口启动了一个服务 , 有没有通用的方法检测服务的 TCP 端口是否启动成功?或者在 B 主机上能不能正常访问该端口?
进一步 , 如果而 A 主机上用 netstat -an 发现端口成功监听了 , 你在 B 主机上的客户端却无法访问 , 那么到底是服务错误还是网络无法到达呢?我们当然可以在 B 主机上用 telnet 探测一下:
telnet 192.168.1.2 8080
但 telnet 并不是专门做这事情的 , 还需要额外安装 , 所以我们在 B 主机上用 netcat:
nc -vz 192.168.1.2 8080
即可 , v 的意思是显示多点信息(verbose) , z 代表不发送数据 。那么如果 B 主机连不上 A 主机的 8080 端口 , 此时你就该检查网络和安全设置了 , 如果连的上那么再去查服务日志去 。
nc 命令后面的 8080 可以写成一个范围进行扫描:
nc -v -v -w3 -z 192.168.1.2 8080-8083
两次 -v 是让它报告更详细的内容 , -w3 是设置扫描超时时间为 3 秒 。
传输测试
你在配置 iptable 或者安全组策略 , 禁止了所有端口 , 但是仅仅开放了 8080 端口 , 你想测试一下该设置成功与否怎么测试?安装个 Nginx 改下端口 , 外面再用 chrome 访问下或者 telnet/curl 测试下??还是 Python -m 启动简单 http 服务 ?其实不用那么麻烦 , 在需要测试的 A 主机上:
nc -l -p 8080
这样就监听了 8080 端口 , 然后在 B 主机上连接过去:
nc 192.168.1.2 8080
两边就可以会话了 , 随便输入点什么按回车 , 另外一边应该会显示出来 , 注意 , openbsd 版本 netcat 用了 -l 以后可以省略 -p 参数 , 写做:nc -l 8080  , 但在 GNU netcat 下面无法运行 , 所以既然推荐写法是加上 -p 参数 , 两个版本都通用 。
老版本的 nc 只要 CTRL+D 发送 EOF 就会断开 , 新版本一律要 CTRL+C 结束 , 不管是服务端还是客户端只要任意一边断开了 , 另一端也就结束了 , 但是 openbsd 版本的 nc 可以加一个 -k 参数让服务端持续工作 。
那么你就可以先用 nc 监听 8080 端口 , 再远端检查可用 , 然后又再次随便监听个 8081 端口 , 远端检测不可用 , 说明你的安全策略配置成功了 , 完全不用安装任何累赘的服务 。
测试 UDP 会话
两台主机 UDP 数据发送不过去 , 问题在哪呢?你得先确认一下两台主机之间 UDP 可以到达 , 这时候没有 nginx 给你用了 , 怎么测试呢?用 python 写个 udp 的 echo 服务??运维不会认你写的工具的 , 即使连不通他也会认为你的程序有 bug , 于是 netcat 又登场了 , 在 A 主机上:


推荐阅读