SSH接続が遅いと感じたときに確認したいこと(Amazon Linux 2023 環境)
こんにちは。
約束に
行けたら行くと
UDP
オペレーション部のかわいです。
さて、今回は一般的なお話で、「SSH接続に時間がかかるときに確認したいこと」について書きたいと思います。
クライアント/サーバには EC2 で Amazon Linux 2023 を使用します。それでは早速いってみましょう
はじめに
まず大前提として「SSH接続に時間がかかる」と言っても原因は様々で、トラブルシューティングには複合的な要素が絡んできます。
この記事では、接続が遅くなるときにチェックすると良い代表的な要因や、設定ファイル上で確認したい項目、
実際にコマンドで時間計測する手順と、筆者の簡易検証結果を紹介します。
本記事がトラブルシュートのヒントになれば幸いです。
SSH接続が遅くなる主な要因
-
ホスト名の名前解決
サーバ側がクライアントの逆引きを行っていると、DNS 応答待ちで遅延が発生することがあります。 -
GSSAPI、Kerberos 認証
環境で使っていない場合でも、設定が有効になっていると余分な処理が生じることがあります。 -
公開鍵検証
鍵長やアルゴリズムにより処理時間が変わります。 -
サーバの負荷状況
CPU やディスク I/O の数値が高いと、応答や処理が遅れることがあります。 -
ネットワーク経路の問題、MTU値など
設定値や経路も接続速度に影響します。
などなど
今回の検証環境
以下環境で確認しました。
#OS
Amazon Linux 2023.8.20250818
#Kernel
6.1.147-172.266.amzn2023.x86_64
#SSHまわり
OpenSSL 3.2.2 4 Jun 2024
openssh-server-8.7p1-8.amzn2023.0.15.x86_64
"sshd_config"ファイルで確認したい箇所
検証環境のバージョンでは、以下の部分がアンコメントされています。
$ cat /etc/ssh/sshd_config | grep -v "#"
Include /etc/ssh/sshd_config.d/*.conf
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no
PermitEmptyPasswords no
Subsystem sftp /usr/libexec/openssh/sftp-server
まずは上記デフォルト設定以外で、別途カスタマイズされている箇所を調査します。
(デフォルト設定のみでは接続遅延を引き起こす要素が考えにくいため)
以下、各項目についての説明です。
■Include /etc/ssh/sshd_config.d/*.conf
指定ディレクトリ内の ".conf" ファイルをインクルードさせる場合、追加の設定をここで上書きできます。指定パス内に別途設定ファイルが置かれていれば、その内容を確認しましょう。
■AuthorizedKeysFile .ssh/authorized_keys
公開鍵(authorized_keys)をユーザのホーム下の ".ssh/authorized_keys" で参照する設定です。
参照ファイルがネットワークストレージ内に置かれていた場合は、読み取り時に I/O/ネットワーク待ちが発生して処理が遅くなる可能性があります。
ローカルディスク上であれば、特に考慮しなくて良いと思います。
■PasswordAuthentication no / PermitEmptyPasswords no
パスワード認証を無効にし、空パスワードを許可しない設定です。
(公開鍵認証のみを許可する設定)
無効になってるので無視。
■Subsystem sftp /usr/libexec/openssh/sftp-server
SFTP のサブシステムを実行する指定。
ssh コマンドでの接続(シェルやコマンド実行)には影響しないので無視。
■AuthorizedKeysCommand /opt/aws/bin/eic_run_authorized_keys %u %f
公開鍵認証のために、sshd が接続時に外部コマンドを実行して公開鍵リストを取得する設定。
AWS 環境では EC2 Instance Connect 用に "eic_run_authorized_keys" が設定されることがあります。
なので、Instance Connect を使用していなければ基本的に遅延ポイントとして考慮しなくて良いと思います。
EC2 インスタンスでの EC2 Instance Connect のインストール
(おまけ)
■UseDNS no
$ sudo sshd -T | grep -i usedns
usedns no
"UseDNS no" が設定されている場合、sshd は接続元 IP アドレスの逆引きを行いません。これにより DNS タイムアウトによる SSH 接続遅延を回避できます。
注意点としては、"authorized_keys"で 'from="hostname.domain,..."' のようにホスト名ベースのアクセス制限を設定している場合は、"UseDNS no"ではホスト名が解決されないため制限が機能しません。その場合はfrom
の値をIPアドレスに変更したり、"UseDNS yes"に設定する必要があります。
sshd で有効になっている設定値の確認方法
以下コマンドから、現在有効になっている設定値を確認できます。
$ sudo sshd -T
port 22
addressfamily any
listenaddress [::]:22
listenaddress 0.0.0.0:22
~~~中略~~~
permitlisten any
permituserenvironment no
pubkeyauthoptions none
この結果からも、意図しない設定値が有効になっていないかを確認できます。
検証してみた
1.SSH 接続時間を測定してみる
一回だけ測りたいときは以下デバッグオプション「-vvv」を付与して、「time」で実行時間を測ります。
$ time ssh -vvv ec2-user@192.0.2.2 -i <鍵ファイルパス>
~~~接続ログ略~~~
real 0m2.841s
user 0m0.009s
sys 0m0.008s
→ 約2.8秒かかりました
※time コマンド結果の見方↓
real コマンド開始から終了まで実際に経過した時間(秒)
user プロセスがユーザ空間(アプリケーション処理)で使った CPU 時間(秒)
sys カーネル空間(システムコール)で使った CPU 時間(秒)
複数回測ってみる
まずは任意のディレクトリ配下に、以下のようなシェルスクリプトを作成します。
「接続用設定」の箇所に、接続先の情報を設定してください。
#!/bin/bash
set -u
# 接続用設定
HOST="<接続先IPアドレス>"
USER="<ユーザ名>"
KEY="<鍵ファイル絶対パス>"
# 以下リモートで実行するコマンド
CMD='exit'
RUNS=10
OUTDIR="ssh_benchmark_$(date +%Y%m%d%H%M%S)"
# known_hostsの確認やパスフレーズ入力で止まらない設定↓(任意)
SSH_OPTS="-o StrictHostKeyChecking=no -o BatchMode=yes -o ConnectTimeout=10"
mkdir -p "$OUTDIR"
echo "結果は $OUTDIR に出力"
for i in $(seq 1 $RUNS); do
echo "=== Run $i / $RUNS ==="
# /usr/bin/time を使って real/user/sys をファイルに出力
/usr/bin/time -f "real=%e user=%U sys=%S" -o "$OUTDIR/time_${i}.txt" \
ssh $SSH_OPTS -vvv -T -i "$KEY" "$USER@$HOST" "$CMD" > "$OUTDIR/ssh_${i}.stdout" 2> "$OUTDIR/ssh_${i}.stderr"
rc=$?
echo "exit_code:$rc" >> "$OUTDIR/time_${i}.txt"
echo "run $i finished (exit $rc)"
sleep 1
done
# サマリ作成
summary="$OUTDIR/summary.csv"
echo "run,real,user,sys,exit_code" > "$summary"
for i in $(seq 1 $RUNS); do
line=$(cat "$OUTDIR/time_${i}.txt" | tr -d '\n')
real=$(echo "$line" | sed -n 's/.*real=\([0-9.]*\).*/\1/p')
user=$(echo "$line" | sed -n 's/.*user=\([0-9.]*\).*/\1/p')
sys=$(echo "$line" | sed -n 's/.*sys=\([0-9.]*\).*/\1/p')
exitc=$(grep -oP 'exit_code:\K.*' "$OUTDIR/time_${i}.txt" || echo "")
echo "$i,$real,$user,$sys,$exitc" >> "$summary"
done
echo "完了。サマリ: $summary"
実行すると、以下のように出力されます。
$ bash ssh_benchmark.sh
結果は ssh_benchmark_20250930053659 に出力します
=== Run 1 / 10 ===
run 1 finished (exit 0)
=== Run 2 / 10 ===
run 2 finished (exit 0)
=== Run 3 / 10 ===
run 3 finished (exit 0)
=== Run 4 / 10 ===
run 4 finished (exit 0)
=== Run 5 / 10 ===
run 5 finished (exit 0)
=== Run 6 / 10 ===
run 6 finished (exit 0)
=== Run 7 / 10 ===
run 7 finished (exit 0)
=== Run 8 / 10 ===
run 8 finished (exit 0)
=== Run 9 / 10 ===
run 9 finished (exit 0)
=== Run 10 / 10 ===
run 10 finished (exit 0)
完了。サマリ: ssh_benchmark_20250930053659/summary.csv
ディレクトリ以下のように10回分のファイルとサマリが生成されます。
「stdout」「stderr」には、個別の接続ログが出力されます。
今回は時間だけを確認したいので、「summary.csv」を確認してみましょう。
$ cat summary.csv
run,real,user,sys,exit_code
1,0.39,0.00,0.01,0
2,0.24,0.00,0.00,0
3,0.22,0.00,0.00,0
4,0.22,0.01,0.00,0
5,0.22,0.01,0.00,0
6,0.22,0.01,0.00,0
7,0.23,0.01,0.00,0
8,0.25,0.01,0.00,0
9,0.23,0.01,0.00,0
10,0.21,0.01,0.00,0
集計して、以下のような数値が出ました。
10回ほど計測することで、接続にバラツキがあるのかがチェックできます。
平均(avg): 約 0.243 s = 243 ms
最小(min): 0.21 s = 210 ms
最大(max): 0.39 s = 390 ms
中央値: 0.225 s = 225 ms
明らかに遅い回がある場合は、デバッグログの中身を見ての調査を行います。
2.パケットキャプチャしてみる
tcpdump を使用して、簡易的にパケットキャプチャを取得してみました。
サーバ側で CLI やターミナルの画面を2画面用意し、1画面でキャプチャを実行、その後もう片方の画面で SSH 接続を実行します。
sudo tcpdump -w ./sample.pcap
# SSH 接続完了後、収集を Ctl + C 等でストップします。
ファイルを確認すると、以下のような出力が確認できます(Wireshark とかで確認するとより見やすいです)。
2025-10-01 01:04:39.131595 IP 192.0.2.1.57558 > 192.0.2.2.22: Flags [S], seq 1262540566, win 62727, options [mss 8961,sackOK,TS val 2245648971 ecr 0,nop,wscale 7], length 0
2025-10-01 01:04:39.133682 IP 192.0.2.2.22 > 192.0.2.1.57558: Flags [S.], seq 1589219062, ack 1262540567, win 62643, options [mss 8961,sackOK,TS val 3349139757 ecr 2245648971,nop,wscale 7], length 0
~~~~~~~~~~~~~~~~~~~~~~~~~~~
2025-10-01 01:04:39.660809 IP 192.0.2.2.22 > 192.0.2.1.57558: Flags [P.], seq 2810:2878, ack 2486, win 475, options [nop,nop,TS val 3349140285 ecr 2245649397], length 68
2025-10-01 01:04:39.660810 IP 192.0.2.2.22 > 192.0.2.1.57558: Flags [P.], seq 2878:2930, ack 2486, win 475, options [nop,nop,TS val 3349140285 ecr 2245649397], length 52
上記では、SYN や ACK の戻りが記録されていることが分かります。
こちらの結果からは、最終応答まで見ると 約0.53秒で接続が確立したことが分かります。
まとめ的な
今回は、Amazon Linux 2023 において SSH 接続が遅いときに確認したい箇所や、トラブルシュートの方法を紹介しました。
踏み台サーバを経由していたり、設定項目をカスタマイズしている場合は、まずは基本的な切り分けから実施するのが良いと思います。
より厳密な調査が必要な場合は、strace や perf 等も選択肢に加わってくるかなと思います。
この記事が何かの役に立てばと思います!では!