如何测量SSH连接的带宽

如何测量SSH连接的带宽

如何测量与远程计算机的特定 SSH 连接的带宽?例如,如果我有一个 SSH 隧道进行端口转发,我想知道有多少数据通过该隧道。特别是,我想知道两个方向的传输速度以及传输的总数据量(两个方向分别)。我怎样才能做到这一点?

操作系统:Debian 11 和 Ubuntu 20.04。

答案1

您可以测量通过 ssh 连接发送的网络流量。

例如:

iftop -i "$iface" -nPf "tcp and port $sport and port $dport"

ssh 连接的数据包将在哪个$iface接口上发送/接收,以及$sport/$dport源和目标 TCP 端口。您还可以f通过指定源 IP 地址和目标 IP 地址来进一步细化过滤器。

或者使用nethogs "$iface"它会给你每个进程的细分。

但这些确实包括以太网、IP、TCP 和 ssh 协议增加的开销,因此不包括加密前通过 ssh 隧道的数据量。

tshark您可以通过解码数据包并告诉您 TCP 有效负载的大小来消除以太网、IP、TCP 开销。但它无法进一步剖析 ssh 协议,因为它是加密的。

为了从不同的渠道处理多少数据ssh,我们需要ssh告诉我们自己。或者,我们可以用来报告进程进行的strace每个read()s 和s 系统调用。对 ssh TCP 套接字的读/写将告诉我们在加密和 ssh 协议开销之后发送了多少数据(应与上面的 TCP 有效负载匹配),而其余大部分应该是它在不同通道上读写的数据(例如用于交互式会话的 tty、用于端口重定向的网络套接字等)。write()ssh

作为概念证明,可以使用 Perl 脚本来完成,例如:

#! /usr/bin/perl
# usage: that-script <pid-of-ssh>

my $pid = shift@ARGV;
my $tunnel_fd;

# list the fds of the process on TCP sockets
open my $lsof, '-|', qw(lsof -wnPa -i tcp -Fd -p), $pid;
while (<$lsof>) {
  if (/^f(\d+)/) {
    # the first fd on a TCP socket is assumed to be that of the ssh connection
    $tunnel_fd = $1;
    last;
  }
}
close $lsof;
die "can't identify tunnel fd\n" unless defined $tunnel_fd;

my %dir;
sub pv {
  open my $fh, '|-', "sh", "-c", q(exec pv "-ctrabN$0" 2>&1 > /dev/null), $_[0];
  $fh->autoflush(1);
  return $fh;
}

open my $strace, '-|', qw(strace -q -s0 -e trace=read,write -e status=successful -a0 -o/dev/stdout -p), $pid;

$dir{"1read"}  = pv "outer  IN";
$dir{"write"}  = pv "inner  IN";
$dir{"read"}   = pv "inner OUT";
$dir{"1write"} = pv "outer OUT";

while (<$strace>) {
  if (/^(read|write)\((\d+).*= (\d+)/) {
    print { $dir{($2 eq $tunnel_fd) . $1} } "." x $3;
  }
}

这里用于pv报告b时间、经过的t时间、即时r进食和a平均速率。

给予类似的东西:

$ sudo ./ssh-stat 26655
outer  IN:  768KiB 0:00:55 [0.00 B/s] [14.0KiB/s]
inner  IN:  718KiB 0:00:55 [0.00 B/s] [13.1KiB/s]
inner OUT: 33.0 B 0:00:55 [0.00 B/s] [ 613miB/s]
outer OUT: 1.62KiB 0:00:55 [0.00 B/s] [30.2 B/s]

例如,这里的 33 个字节inner OUT是与我在终端上键入的键相对应发送的几个字符,而outer OUT是作为 ssh 协议的一部分发送的数据(以封装这些字符,但我也想确认在其他方向)。

要获得每个 ssh 通道的详细信息,您可以对其进行扩展,为每个 fd 提供单独的报告。其中描述每个 fd-yy的选项可以提供帮助。strace例如:

$ sudo strace -yy -q -s0 -e trace=read,write -e status=successful -a0 -o /dev/stdout -p 26655
read(6</dev/pts/1<char 136:1>>, ""..., 16384) = 3
write(3<TCP:[127.0.0.1:42334->127.0.0.1:22]>, ""..., 44) = 44
read(3<TCP:[127.0.0.1:42334->127.0.0.1:22]>, ""..., 8192) = 52
write(7</dev/pts/1<char 136:1>>, ""..., 16) = 16
read(6</dev/pts/1<char 136:1>>, ""..., 16384) = 3
write(3<TCP:[127.0.0.1:42334->127.0.0.1:22]>, ""..., 44) = 44
read(3<TCP:[127.0.0.1:42334->127.0.0.1:22]>, ""..., 8192) = 60
write(7</dev/pts/1<char 136:1>>, ""..., 26) = 26
read(3<TCP:[127.0.0.1:42334->127.0.0.1:22]>, ""..., 8192) = 44
write(9<TCP:[127.0.0.1:12344->127.0.0.1:43144]>, ""..., 3) = 3
read(9<TCP:[127.0.0.1:12344->127.0.0.1:43144]>, ""..., 16384) = 11
write(3<TCP:[127.0.0.1:42334->127.0.0.1:22]>, ""..., 52) = 52

在我的测试中显示了 ssh 连接上有多少数据 (fd 3)、从/到 tty (fds 6, 7) 的数据量、从本地端口转发到端口 12344 的数据量 (fd 9) 。

相关内容