ProxyCommandを使用してSSH速度を劇的に向上させます。しかし、その理由は何ですか?

ProxyCommandを使用してSSH速度を劇的に向上させます。しかし、その理由は何ですか?

TL、DRバージョン

このASCII変換を見るまたはこの動画- その後、これが起こる理由を学びます。以下のテキストの説明は追加のコンテキストを提供します。

設定の詳細

  • sshMachine 1は、Armbianを実行しているOrange PI Zero(SBC)に接続されたビルドを構築したArch Linuxノートブックです。
  • SBC自体はIP 192.168.1.150のイーサネットを介してDSLルータに接続されます。
  • ラップトップは公式Raspberry PI WiFiアダプタを使用してWiFi経由でルーターに接続されます。
  • イーサネット経由でDSLルーターに接続されている他のノートブック(マシン2)があります。

トポロジー

iperf3を使用したベンチマークリンク

ノートブックとSBCの間のリンクは、以下を使用してベンチマークしたときにiperf3理論的な56MBits /秒未満でした。(アパート)

具体的には、iperf3 -sSBCで実行した後、ノートブックで次のコマンドを実行します。

# iperf3 -c 192.168.1.150
Connecting to host 192.168.1.150, port 5201
[  5] local 192.168.1.89 port 57954 connected to 192.168.1.150 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  2.99 MBytes  25.1 Mbits/sec    0    112 KBytes       
...
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  28.0 MBytes  23.5 Mbits/sec    5             sender
[  5]   0.00-10.00  sec  27.8 MBytes  23.4 Mbits/sec                  receiver

iperf Done.

# iperf3 -c 192.168.1.150 -R
Connecting to host 192.168.1.150, port 5201
Reverse mode, remote host 192.168.1.150 is sending
[  5] local 192.168.1.89 port 57960 connected to 192.168.1.150 port 5201
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec  3.43 MBytes  28.7 Mbits/sec                  
...                
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  39.2 MBytes  32.9 Mbits/sec  375             sender
[  5]   0.00-10.00  sec  37.7 MBytes  31.6 Mbits/sec                  receiver

したがって、デフォルトでは、SBCへのアップロード速度は約24MBits /秒、-RSBC()からダウンロードする速度は最大32MBits /秒です。

SSHを使用したベンチマーク

これを念頭に置いて、SSHがどのように実行されるかを見てみましょう。この記事を書く最初の問題はSSHを使用することでしたrsyncborgbackupどちらもトランスポート層としてSSHを使用します...したがって、同じリンクでSSHがどのように実行されるかを見てみましょう。

# cat /dev/urandom | \
    pv -ptebar | \
    ssh  [email protected] 'cat >/dev/null'
20.3MiB 0:00:52 [ 315KiB/s] [ 394KiB/s]

まあ、この速度は本当に素晴らしいです!予想されるリンク速度よりはるかに遅いです。 (わからない場合に備えて、pv -ptevar現在と平均のデータレートを示します。この場合、/dev/urandomSSHを介してデータを読み取り、SBCにデータを送信することは、平均400KB / s、つまり3.2MBits /秒です。予想される24MBits /秒未満)。

リンクが13%の容量でのみ機能するのはなぜですか?

たぶん私たちは間違っていますか/dev/urandom

# cat /dev/urandom | pv -ptebar > /dev/null
834MiB 0:00:04 [ 216MiB/s] [ 208MiB/s]

いいえ、決してそうではありません。

たぶんSBC自体ですか?処理速度が遅すぎるのではないでしょうか?同じSSHコマンド(例:SBCへのデータ転送)を実行してみましょう。しかし、今回はイーサネット経由で接続された別のマシン(マシン2)で実行してみましょう。

# cat /dev/urandom | \
    pv -ptebar | \
    ssh  [email protected] 'cat >/dev/null'
240MiB 0:00:31 [10.7MiB/s] [7.69MiB/s] 

いいえ、これはうまくいきます。 SBCのSSHデーモンは、イーサネットリンクで提供される11MBytes /秒(100MBits /秒)を(簡単に)処理できます。

これを行うと、SBCのCPUがロードされますか?

CPUが簡単に処理します。

いいえ。

だから...

  • ネットワークの観点からは、iperf310倍の速度を達成できるはずです。
  • 私達のCPUは負荷に容易に適応します。
  • ...他の種類のI / O(ドライブなど)は扱いません。

結局何が起こったのですか?

NetcatとProxyCommandが救出に出ました。

通常の既存の接続を試してみましょうnetcat。予想と同じくらい速く走りますか?

SBCから:

# nc -l -p 9988 | pv -ptebar > /dev/null

ノートブックの場合:

# cat /dev/urandom | pv -ptebar | nc 192.168.1.150 9988
117MiB 0:00:33 [3.82MiB/s] [3.57MiB/s] 

効果がある!そして予想される速度で実行されます。はるかに良い、10倍良いです。

もしそうなら、ProxyCommandを使ってncを使ってSSHを実行するとどうなりますか?

# cat /dev/urandom | \
    pv -ptebar | \
    ssh -o "Proxycommand nc %h %p" [email protected] 'cat >/dev/null'
101MiB 0:00:30 [3.38MiB/s] [3.33MiB/s]

働く! 10倍速いです。

今少し混乱しています。ncのように "naked"を使用するとき、Proxycommand基本的にSSHと同じことをするのではありませんか?つまり、ソケットを作成してSBCのポート22に接続し、ここにSSHプロトコルを追加しますか?

最終速度になぜそんなに大きな違いがありますか?

PS:これはありません学業練習-borgその結果、バックアップは10倍速く実行されます。なぜそうなのか分からない :-)

編集する:コース「ビデオ」を追加ここ。 ifconfigの出力から送信されたパケットを数えてみると、両方のテストで40MBのデータを送信し、約30Kパケットで送信したことが明らかです。使用しないときははるかに遅いですProxyCommand

ベストアンサー1

コメントでアイデアを提供してくださった方々に心から感謝します。私はこれらすべてを経験しました:

tcpdump を使用してパケットを記録し、WireShark の内容を比較します。

# tcpdump -i wlan0 -w good.ssh & \
     cat signature | ssh -o "ProxyCommand nc %h %p" \
        [email protected] 'cat | md5sum' ; \
     killall tcpdump
# tcpdump -i wlan0 -w bad.ssh & \
     cat signature | ssh [email protected] 'cat | md5sum' ; \
     killall tcpdump

記録されたパケットに大きな違いはありません。

トラフィック形式の確認

これについて何も知らないが、「tc」マンページを見てこれを確認することができました。

  • tc filter show何も返さない
  • tc class show何も返さない
  • tc qdisc show

...次を返します。

qdisc noqueue 0: dev lo root refcnt 2
qdisc noqueue 0: dev docker0 root refcnt 2
qdisc fq_codel 0: dev wlan0 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn 

...これは「ssh」と「nc」を区別できないようです。実際には、トラフィックの調整がプロセスレベルで機能しているかどうかはわかりません(アドレス/ポート/差別化で動作することを期待しています))のIPヘッダーサービスフィールド。

Arch Linux SSHクライアントの潜在的な「賢さ」を避けるためのDebian Chroot

いいえ、結果は同じです。

最後に - Nagel

送信者からstraceを実行します...

pv data | strace -T -ttt -f ssh 192.168.1.150 'cat | md5sum' 2>bad.log

...そして、データが転送されるソケットで実際に何が起こっているのかを確認するために、実際の転送が始まる前に次の「設定」を確認しました。

1522665534.007805 getsockopt(3, SOL_TCP, TCP_NODELAY, [0], [4]) = 0 <0.000025>
1522665534.007899 setsockopt(3, SOL_TCP, TCP_NODELAY, [1], 4) = 0 <0.000021>

Nagleのアルゴリズムを無効にするようにSSHソケットを設定します。 Google でこれに関するすべての内容を読むことができます。しかし、これが意味するのは、SSHが帯域幅よりも応答性を優先するということです。これは、リモートチェックから出るまで「遅延」するのではなく、このソケットに書き込まれたすべてのコンテンツをすぐに送信するようにカーネルに指示します。

簡単に言えば、これは基本的な構成では、SSHがデータを転送する良い方法ではないことを意味します。つまり、使用されているリンクが遅い場合(多くのWiFiリンクの場合のように)。 「ほとんどのヘッダー」パケットをワイヤレスで送信すると、帯域幅が無駄になります!

これが実際に犯人であることを証明するために、LD_PRELOADを使用してこの特定のシステムコールを「削除」しました。

$ cat force_nagle.c

#include <stdio.h>
#include <dlfcn.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>

int (*osetsockopt) (int socket, int level, int option_name,
           const void *option_value, socklen_t option_len) = NULL;

int setsockopt(int socket, int level, int option_name,
           const void *option_value, socklen_t option_len)
{
    int ret;
    if (!osetsockopt) {
        osetsockopt = dlsym(RTLD_NEXT, "setsockopt");
    }

    if (option_name == TCP_NODELAY) {
        puts("No, Mr Nagle stays.");
        return 0;
    }
    ret = osetsockopt(socket, level, option_name, option_value, option_len);
    return ret;
}

$ gcc -fPIC -D_GNU_SOURCE -shared -o force_nagle.so force_nagle.c -ldl

$ pv /dev/shm/data | LD_PRELOAD=./force_nagle.so ssh [email protected] 'cat >/dev/null'
No, Mr Nagle stays.
No, Mr Nagle stays.
 100MiB 0:00:29 [3.38MiB/s] [3.38MiB/s] [================================>] 100%   

そこには完璧な速度があります(iperf3ほど高速です)。

ストーリー詐欺

決してあきらめないでください:-)

rsyncSSH経由でデータを転送するなどのツールを使用していて、borgbackupリンクが遅い場合は、Nagleを無効にしてSSHをブロックするか(上記を参照)、Nagleを使用してProxyCommandSSHを切り替えてみてくださいnc。これは$ HOME /で自動的に実行できます。 SSH/構成から:

$ cat .ssh/config
...
Host orangepi
    Hostname 192.168.1.150
    User root
    Port 22
    # Compression no
    # Cipher None
    ProxyCommand nc %h %p
...

nc...以降、ssh / rsync / borgbackupでターゲットホストとして "orangepi"を使用するすべての操作が接続に使用されます(したがってNagleを気にしないでください)。

おすすめ記事