1 - netstat 命令

netstat 命令

2 - lsof 命令

lsof 命令

3 - ss 命令

ss 命令

介绍

ss 是 Socket Statistics 的缩写。

ss 命令可以用来获取 socket 统计信息,它显示的内容和 netstat 类似。但 ss 的优势在于它能够显示更多更详细的有关 TCP 和连接状态的信息,而且比 netstat 更快。当服务器的 socket 连接数量变得非常大时,无论是使用 netstat 命令还是直接 cat /proc/net/tcp,执行速度都会很慢。

ss 命令利用到了 TCP 协议栈中 tcp_diag。tcp_diag 是一个用于分析统计的模块,可以获得 Linux 内核中第一手的信息,因此 ss 命令的性能会好很多。

用法

常用选项

-h, –help 帮助

-V, –version 显示版本号

-t, –tcp 显示 TCP 协议的 sockets

-u, –udp 显示 UDP 协议的 sockets

-x, –unix 显示 unix domain sockets,与 -f 选项相同

-n, –numeric 不解析服务的名称,如 “22” 端口不会显示成 “ssh”

-l, –listening 只显示处于监听状态的端口

-p, –processes 显示监听端口的进程(Ubuntu 上需要 sudo)

-a, –all 对 TCP 协议来说,既包含监听的端口,也包含建立的连接

-r, –resolve 把 IP 解释为域名,把端口号解释为协议名称

具体可见:

s -h
Usage: ss [ OPTIONS ]
       ss [ OPTIONS ] [ FILTER ]
   -h, --help          this message
   -V, --version       output version information
   -n, --numeric       don't resolve service names
   -r, --resolve       resolve host names
   -a, --all           display all sockets
   -l, --listening     display listening sockets
   -o, --options       show timer information
   -e, --extended      show detailed socket information
   -m, --memory        show socket memory usage
   -p, --processes     show process using socket
   -i, --info          show internal TCP information
       --tipcinfo      show internal tipc socket information
   -s, --summary       show socket usage summary
       --tos           show tos and priority information
   -b, --bpf           show bpf filter socket information
   -E, --events        continually display sockets as they are destroyed
   -Z, --context       display process SELinux security contexts
   -z, --contexts      display process and socket SELinux security contexts
   -N, --net           switch to the specified network namespace name

   -4, --ipv4          display only IP version 4 sockets
   -6, --ipv6          display only IP version 6 sockets
   -0, --packet        display PACKET sockets
   -t, --tcp           display only TCP sockets
   -S, --sctp          display only SCTP sockets
   -u, --udp           display only UDP sockets
   -d, --dccp          display only DCCP sockets
   -w, --raw           display only RAW sockets
   -x, --unix          display only Unix domain sockets
       --tipc          display only TIPC sockets
       --vsock         display only vsock sockets
   -f, --family=FAMILY display sockets of type FAMILY
       FAMILY := {inet|inet6|link|unix|netlink|vsock|tipc|xdp|help}

   -K, --kill          forcibly close sockets, display what was closed
   -H, --no-header     Suppress header line
   -O, --oneline       socket's data printed on a single line

   -A, --query=QUERY, --socket=QUERY
       QUERY := {all|inet|tcp|udp|raw|unix|unix_dgram|unix_stream|unix_seqpacket|packet|netlink|vsock_stream|vsock_dgram|tipc}[,QUERY]

   -D, --diag=FILE     Dump raw information about TCP sockets to FILE
   -F, --filter=FILE   read filter information from FILE
       FILTER := [ state STATE-FILTER ] [ EXPRESSION ]
       STATE-FILTER := {all|connected|synchronized|bucket|big|TCP-STATES}
         TCP-STATES := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|closed|close-wait|last-ack|listening|closing}
          connected := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}
       synchronized := {established|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}
             bucket := {syn-recv|time-wait}
                big := {established|syn-sent|fin-wait-{1,2}|closed|close-wait|last-ack|listening|closing}

4 - route 命令

route 命令
route -n                                                
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.40  0.0.0.0         UG    100    0        0 ens1
0.0.0.0         192.168.0.1     0.0.0.0         UG    101    0        0 eno1
10.0.0.0        192.168.100.40  255.0.0.0       UG    0      0        0 ens1
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 ens1
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.0.0     0.0.0.0         255.255.255.0   U     101    0        0 eno1
192.168.100.0   0.0.0.0         255.255.255.0   U     100    0        0 ens1

5 - traceroute 命令

traceroute 命令用于追踪数据包在网络上的传输时的全部路径

安装

ubuntu 默认居然没有自带 traceroute 命令,apt 安装一个:

sudo apt install traceroute

参考资料

6 - wireshark

wireshark

6.1 - wireshark 介绍

Wireshark是广泛使用的网络协议分析器

Wireshark是世界上最重要和广泛使用的网络协议分析器。它可以让你在微观层面上看到网络上发生的事情,并且是许多商业和非盈利企业、政府机构和教育机构的事实(通常也是法律)标准。Wireshark的发展得益于全球网络专家的志愿贡献,是Gerald Combs在1998年开始的项目的延续。

介绍

https://www.wireshark.org/

功能介绍

Wireshark具有丰富的功能,包括以下内容:

  • 对数百种协议进行深入探查,并不断增加更多的协议
  • 实时捕获和离线分析
  • 标准的三窗体数据包浏览器
  • 多平台。可在Windows、Linux、macOS、Solaris、FreeBSD、NetBSD和其他许多平台上运行
  • 捕获的网络数据可以通过GUI或TTY模式的TShark工具进行浏览
  • 行业中最强大的显示过滤器
  • 丰富的VoIP分析
  • 读取/写入许多不同的捕获文件格式。tcpdump (libpcap), Pcap NG, Catapult DCT2000, Cisco Secure IDS iplog, Microsoft Network Monitor, Network General Sniffer® (compressed and uncompressed), Sniffer® Pro, and NetXray®, Network Instruments Observer, NetScreen snoop, Novell LANalyzer, RADCOM WAN/LAN Analyzer, Shomiti/Finisar Surveyor, Tektronix K12xx, Visual Networks Visual UpTime, WildPackets EtherPeek/TokenPeek/AiroPeek, 和许多其他产品。
  • 用gzip压缩的捕获文件可以在运行中解压缩
  • 可以从以太网、IEEE 802.11、PPP/HDLC、ATM、蓝牙、USB、令牌环、帧中继、FDDI等读取实时数据(取决于您的平台)
  • 支持许多协议的解密,包括IPsec、ISAKMP、Kerberos、SNMPv3、SSL/TLS、WEP和WPA/WPA2
  • 着色规则可应用于数据包列表,以进行快速、直观的分析
  • 输出可以导出为XML、PostScript®、CSV或纯文本

资料

官方资料

https://www.wireshark.org/#learnWS

  • 培训
  • 用户文档
  • 开发文档
  • 各种视频和演讲

6.2 - 安装 wireshark

在 ubuntu 上安装 wireshark

安装

安装最新稳定版本

ubuntu 下可以直接安装,但默认的版本是3.2.3,发布于2019年,而最新的版本是 3.6.3。

参考官方文档: https://launchpad.net/~wireshark-dev/+archive/ubuntu/stable

安装最新稳定版本:

sudo add-apt-repository ppa:wireshark-dev/stable
sudo apt-get update
sudo apt install wireshark

但这个方式安装下来的版本是 3.4.8-1

$ apt-cache madison wireshark
 wireshark | 3.4.8-1~ubuntu20.04.0+wiresharkdevstable1 | http://ppa.launchpad.net/wireshark-dev/stable/ubuntu focal/main amd64 Packages
 wireshark |    3.2.3-1 | http://mirrors.aliyun.com/ubuntu focal/universe amd64 Packages

安装最新开发版本

如果要安装最新的dev版本,可以考虑从源码编译,参考:

https://www.linuxfromscratch.org/blfs/view/svn/basicnet/wireshark.html

但这个实在麻烦了一点。好在ubuntu下有ppt:

sudo add-apt-repository ppa:dreibh/ppa
sudo apt update
sudo apt -y install wireshark

最新的开发版本已经是 3.7.0 了:

$ apt-cache madison wireshark
 wireshark | 3.7.0+git20220406073638~7adc301d-1ppa~focal1 | http://ppa.launchpad.net/dreibh/ppa/ubuntu focal/main amd64 Packages
 wireshark | 3.4.8-1~ubuntu20.04.0+wiresharkdevstable1 | http://ppa.launchpad.net/wireshark-dev/stable/ubuntu focal/main amd64 Packages
 wireshark |    3.2.3-1 | http://mirrors.aliyun.com/ubuntu focal/universe amd64 Packages

配置

允许非超级用户捕获数据包

启动时提示是否允许非超级用户捕获数据包:

permisions

按照提示操作:

sudo dpkg-reconfigure wireshark-common

configure

选择 yes,然后将自己加入到 wireshark group:

sudo usermod -a -G wireshark $USER

注销账号再重新登录。

参考资料

6.3 - filter的用法

wireshark filter 的用法

6.3.1 - filter 概述

wireshark filter 概述

参考资料

6.4 - 各种协议的抓包方式

wireshark 各种协议的抓包方式

6.4.1 - 抓取 http 包

在 ubuntu 上安装 wireshark 抓取 http 包

抓取本地http包

目标是抓取访问 http://localhost:1313/ 地址的HTTP包,设置中选择 “Loopback: lo”, filter 设置为 http and tcp.port=1313:

http-local

以下是抓取多次 http 交互的一个例子,这是 dapr java-sdk 中的一个bug,当时排查时发现 https://github.com/dapr/java-sdk/issues/709

http-example

7 - Linux ip 命令

Linux ip 命令

7.1 - 使用 ip 命令操作路由

使用 ip 命令操作路由

添加路由

$ route -n                                                
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.40  0.0.0.0         UG    100    0        0 ens1
0.0.0.0         192.168.0.1     0.0.0.0         UG    101    0        0 eno1
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 ens1
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.0.0     0.0.0.0         255.255.255.0   U     101    0        0 eno1
192.168.100.0   0.0.0.0         255.255.255.0   U     100    0        0 ens1

为了访问 10.0.0.0/8 号段,增加一条路由规则:

sudo ip route add 10.0.0.0/8 via 192.168.100.40 dev ens1

完成后的路由情况:

route -n                                                
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.40  0.0.0.0         UG    100    0        0 ens1
0.0.0.0         192.168.0.1     0.0.0.0         UG    101    0        0 eno1
10.0.0.0        192.168.100.40  255.0.0.0       UG    0      0        0 ens1
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 ens1
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.0.0     0.0.0.0         255.255.255.0   U     101    0        0 eno1
192.168.100.0   0.0.0.0         255.255.255.0   U     100    0        0 ens1

参考资料

8 - nfs 命令

Linux nfs 相关命令

8.1 - nfs命令概述

常用nfs命令

安装

nfs 服务器和客户端的安装见 安装配置nfs文件共享

使用

列出远程nfs服务器上的挂载信息,然后在本地建立目录并挂载:

# 查看远程服务器的挂载情况
$ showmount --exports 192.168.0.40 
Export list for 192.168.0.40:
/mnt/d         192.168.0.0/16
/mnt/nfs-share 192.168.0.0/16

# 挂载到本地
$ mkdir -p /mnt/d
$ sudo mount -t nfs 192.168.0.40:/mnt/d /mnt/d

# 不使用时卸载
$ sudo umount /mnt/d

资料

8.2 - showmount命令

showmount用来显示nfs服务器的挂载信息

使用

$ showmount --exports 192.168.0.40 
Export list for 192.168.0.40:
/mnt/d         192.168.0.0/16
/mnt/nfs-share 192.168.0.0/16

资料

8.4 - NFSoRDMA

准备工作

正确安装网卡的 MLNX_OFED 驱动

注意在安装时,一定要加 --add-kernel-support 参数,否则只能重新安装。我之前安装 MLNX_OFED 驱动时没有加这个参数,因此不得不重新安装:

 sudo ./mlnxofedinstall --without-fw-update --force --add-kernel-support

这个命令会删除现有已经安装的驱动,然后重新安装

安装 rdma 相关的包

参考 redhat 的文档 通过 RDMA(NFSoRDMA)启用 NFS

在 nfs 服务器端和客户端都安装 rdma-core :

sudo apt install rdma-core

并确保 /etc/rdma/modules/rdma.conf 文件中没有注释掉 xprtrdmasvcrdma 这两行:

# NFS over RDMA client support
xprtrdma

# NFS over RDMA server support
svcrdma

确保 rdma 相关的 mod 正确装载

参考 oracle 的这个文档, Using the NFS over RDMA Client

在 nfs 服务器端,检查:

sudo modprobe svcrdma

在 nfs 客户端,检查:

sudo modprobe xprtrdma

备注: svcrdma 和 xprtrdma 似乎都只是 rpcrdma mod 的别名??

sudo modprobe -r xprtrdma
modprobe: FATAL: Module rpcrdma is in use.

安装

安装 VAST-NFS Client Driver

https://vastnfs.vastdata.com/docs/4.0/Intro.html

下载最新版本:

curl -sSf https://vast-nfs.s3.amazonaws.com/download.sh | bash

Checking latest version...
Downloaded: vastnfs-4.0.18.tar.xz

解压缩:

tar xvf vastnfs-4.0.18.tar.xz
cd vastnfs-4.0.18

编译:

./build.sh bin

......
dpkg-buildpackage: info: binary-only upload (no source included)
total 912
-rw-r--r-- 1 sky sky 933788 Aug 11 02:17 vastnfs-dkms_4.0.18-vastdata-MLNX.OFED.LINUX-4.9-6.0.6.0_all.deb
------------------------------------------------------------------

Output in dist/

total 912
-rw-r--r-- 1 sky sky 933788 Aug 11 02:17 vastnfs-dkms_4.0.18-vastdata-MLNX.OFED.LINUX-4.9-6.0.6.0_all.deb

注意这里,如果编译出来的文件名是类似上面的 “vastnfs-dkms_4.0.18-vastdata-MLNX.OFED.LINUX-4.9-6.0.6.0_all.deb”,是有问题的,需要重新安装。

这是因为 MLNX_OFED 驱动在安装是没有加 --add-kernel-support 参数。如果 MLNX_OFED 驱动在安装时有正确的加 --add-kernel-support 参数,则编译出来的文件名会类似 vastnfs-modules_4.0.18-vastdata-MLNX.OFED.LINUX-4.9-6.0.6.0.kver.5.4.0-156-generic_amd64.deb 这样带有 linux 内核的版本。

安装:

cd dist
# 注意这个文件是有问题的
# sudo apt install ./vastnfs-dkms_4.0.18-vastdata-MLNX.OFED.LINUX-4.9-6.0.6.0_all.deb
# 这个文件才是对的
sudo apt install ./vastnfs-modules_4.0.18-vastdata-MLNX.OFED.LINUX-4.9-6.0.6.0.kver.5.4.0-156-generic_amd64.deb

......
compat_nfs_ssc.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/5.4.0-156-generic/updates/dkms/

depmod...

DKMS: install completed.

更新 initramfs:

sudo update-initramfs -u -k `uname -r`

update-initramfs: Generating /boot/initrd.img-5.4.0-156-generic

重启机器。然后检验:

$ cat /sys/module/sunrpc/srcversion
FAA3D4CDBA86B8279289A02

$ modinfo sunrpc | grep srcversion
srcversion:     FAA3D4CDBA86B8279289A02

两个 srcversion 要一致。

$ vastnfs-ctl status          

version: 4.0.18-vastdata-MLNX.OFED.LINUX-4.9-6.0.6.0
kernel modules: sunrpc rpcrdma compat_nfs_ssc lockd nfs_acl auth_rpcgss nfsd nfs nfsv3
services: rpcbind.socket rpcbind
rpc_pipefs: /run/rpc_pipefs

启动 nfs 服务器端

sudo vi /etc/exports

设置 nfs export 的内容,比如我这里要导出两个地址:

/mnt/data/share 192.168.0.0/16(fsid=0,rw,async,insecure,no_root_squash,no_subtree_check)
/mnt/data/pve-share 192.168.0.0/16(fsid=0,rw,async,insecure,no_root_squash,no_subtree_check)

重启 nfs-server :

sudo systemctl restart nfs-server

关键设置,在启动 nfs-server 之后再设置 rdma 的端口 20049:

# 还不能用 sudo,会宝座
sudo echo rdma 20049 > /proc/fs/nfsd/portlist
zsh: permission denied: /proc/fs/nfsd/portlist

# 要先 su 到 root
sudo su
# 看一眼现在的设置, rdma 20049 端口的设置在 restart nfs-server 之后就消失了
vi /proc/fs/nfsd/portlist
# 也不能通过 vi 命令来修改,会无法保存文件

# 可以这样修改
echo rdma 20049 > /proc/fs/nfsd/portlist

这个时候 /proc/fs/nfsd/portlist 文件的内容是这样的:

rdma 20049
rdma 20049
udp 2049
tcp 2049
udp 2049
tcp 2049

nfs 客户端mount

在 nfs 客户端执行命令,尝试 mount :

sudo mount -t nfs -o vers=3,proto=rdma,port=20049 192.168.99.100:/mnt/data/share /mnt/nfs-fast

如果 mount 命令一直卡住不返回,一般是 nfs 服务器端无法连接,在 ip 地址和路径没问题的情况下,最大可能性就是 20049 端口没有开启或者无法连接。

如果成功,此时就可以看到服务器端的文件被 mount 过来了。

验证

执行 dd 命令读取一个 100G 的大文件验证一下:

dd if=/mnt/nfs-fast/temp/test1.img of=/dev/null bs=8M
12800+0 records in
12800+0 records out
107374182400 bytes (107 GB, 100 GiB) copied, 72.2484 s, 1.5 GB/s

很遗憾,1.5GB/s 的速度明显不是 rdma 开启后应有的速度。

再次重复上面的测试,期间通过 top 命令查看 nfs 服务器端的 cpu 使用情况:

top - 06:56:12 up  3:15,  2 users,  load average: 0.90, 0.36, 0.14
Tasks: 259 total,   1 running, 258 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us, 10.2 sy,  0.0 ni, 88.5 id,  1.0 wa,  0.0 hi,  0.3 si,  0.0 st
MiB Mem :  31841.3 total,    261.1 free,   1129.2 used,  30451.0 buff/cache
MiB Swap:   8192.0 total,   8180.2 free,     11.8 used.  30244.3 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                
   5950 root      20   0       0      0      0 D  45.5   0.0   0:45.37 nfsd  
   5951 root      20   0       0      0      0 S  45.2   0.0   0:46.05 nfsd  
    153 root      20   0       0      0      0 S  32.2   0.0   1:10.76 kswapd0 
    744 root       0 -20       0      0      0 I   2.3   0.0   0:02.72 kworker/5:1H-ib-comp-wq 
   5949 root      20   0       0      0      0 S   1.0   0.0   0:00.91 nfsd  
     10 root      20   0       0      0      0 I   0.3   0.0   0:03.39 rcu_sched  

直接在 nfs 服务器端执行 dd 命令读取这个 100G 的大文件试试:

dd if=/mnt/data/share/temp/test1.img of=/dev/null bs=8M

12800+0 records in
12800+0 records out
107374182400 bytes (107 GB, 100 GiB) copied, 25.8021 s, 4.2 GB/s

可以看到读取的速度是 4.2 GB/s,可见ssd硬盘的读取速度(4.2 GB/s)远远大于 nfs 传输的速度(1.5 GB/s)。

推断:从传输速度上看,rdma 应该是没有开启。

期间通过 top 命令查看 nfs 服务器端的 cpu 使用情况:

top - 06:59:16 up  3:18,  2 users,  load average: 0.41, 0.40, 0.20
Tasks: 261 total,   2 running, 259 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  9.2 sy,  0.0 ni, 89.7 id,  0.9 wa,  0.0 hi,  0.3 si,  0.0 st
MiB Mem :  31841.3 total,    238.3 free,   1131.8 used,  30471.2 buff/cache
MiB Swap:   8192.0 total,   8169.7 free,     22.2 used.  30242.1 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND  
   6046 root      20   0   13724   9896   1728 R  89.0   0.0   0:17.25 dd 
    153 root      20   0       0      0      0 S  23.0   0.0   1:29.40 kswapd0 
     10 root      20   0       0      0      0 I   0.3   0.0   0:03.57 rcu_sched    
   5866 root      20   0       0      0      0 I   0.3   0.0   0:01.62 kworker/u24:2-mlx4_en  
   5955 root      20   0       0      0      0 I   0.3   0.0   0:00.04 kworker/0:2-events  

发现和走 nfs 传输相比,服务器端的 cpu 消耗基本相当: 10.2 sy, 0.0 ni, 88.5 id9.2 sy, 0.0 ni, 89.7 id

推断:从nfs服务器端 cpu 占用上看,rdma 应该是开启了。

现在就有点矛盾了!

参考资料

9 - nc命令

netcat命令

使用

检查端口:

# 查看单个端口
$ nc  -zv  192.168.0.40 2049
Connection to 192.168.0.40 2049 port [tcp/nfs] succeeded!

# 查看多个端口
$ nc -zv 192.168.56.10 80 22 21

# 查看指定端口范围 
$ nc -zv 192.168.56.10 20-80

-w 可用于设置超时:

nc -w 5 -zv  192.168.0.40 2049

参考资料