トラブルシューティングの極意―達人に訊く問題解決のヒント

第2回 [サーバ・インフラ・ネットワーク編]SSHでありがちなトラブルとその対策―不都合なくSSHを使えていますか?

この記事を読むのに必要な時間:およそ 4 分

トラシュー事例2
「SSHのログインが遅い」

sshコマンド実行後,ログインに何秒も待たされる場合があります。これはサーバ側のsshd_configの設定が原因というケースが多くあります。よくある原因としてはホストの名前解決によるもので,sshdにはUseDNSという設定値があり,デフォルトでyesが設定されています注1⁠。

この設定が有効の場合,sshでクライアントからサーバへ接続する際に,接続元のクライアントのIPアドレスから逆引きしてホスト名を取得し,さらに正引きしてIPアドレスに戻して,もとのIPアドレスと同じになるかどうかをsshdがチェックします。サーバ側のDNSの設定(たとえば,resolv.conf,hosts,nsswitch.confなど)が影響して,この名前解決がうまくいかずにタイムアウトを待ってしまう場合に,ログインが非常に遅くなってしまいます。こういった場合は,UseDNSをnoに設定して問題を回避できます。

もう1つ,ログインが遅くなる原因として,GSSAPIによる認証が有効になっていることが挙げられます。GSSAPIとは,Generic Security Standard Application Programming Interfaceの略で,RFC 2743で定義されている認証方式です。Kerberosと組み合わせて使われることが多く,シングルサインオンを目的として使われています。sshd_configにはGSSAPIAuthenticationという設定が用意されており,デフォルトはnoとなっているため,影響はほとんどないと思われますが,もしyesになっていてシングルサインオンなどでGSSAPIを使っていない場合はnoにして無効にしておきましょう。

注1)
次期バージョンのOpenSSH 6.8でデフォルトがnoになる予定。

トラシュー事例3
「エージェント転送がうまくいかない」

SSHにはエージェント転送という機能があり,正しく使いこなせると非常に便利で,SSHに関わる作業効率が向上するでしょう。しかし,正しく理解していないと使い方を間違っていたり,エージェントが機能していなかったりとトラブルが多く,便利な機能にもかかわらず結局使っていないといったことをよく見かけます。まずは,エージェント転送の基本的な動作について解説します。

エージェント転送について理解を深める前に,SSHにおける公開鍵認証の流れを見てみましょう図3⁠。

図3 SSHにおける公開鍵認証

図3 SSHにおける公開鍵認証

公開鍵認証方式では,図3のように秘密鍵と公開鍵を使って認証が行われます。この例では,クライアントから1台のサーバへ接続するような非常にシンプルな構成ですが,実際の運用ではサーバからさらに別のサーバへログインすることが多くあります。いわゆる「踏み台」となるサーバを経由して,その先にある複数のサーバへログインするというケースです。この場合に秘密鍵の置き場所はどのようにすべきでしょうか。

秘密鍵を踏み台となるサーバに設置することで,さらに先のサーバへログインすることはできますが,秘密鍵をサーバに置くことはお勧めできません。万が一,秘密鍵が置いてあるサーバに誰でもアクセスできてしまうことになってしまい,秘密鍵を奪われた場合,あらゆるサーバへログインすることが可能になるかもしれません。秘密鍵は特別な理由がない限りは手元に置きましょう。

それでは,手元にしかない秘密鍵を使って,さらに先のサーバへログインするにはどうしたらよいでしょうか。ここで,エージェント転送と呼ばれる機能を使います。エージェント転送を使うことで,クライアントから踏み台となるサーバへログインし,そこからさらに別のサーバへログインすることができます。

エージェント転送を使うには,ssh-agentコマンドを利用します。ssh-agentを起動すると,鍵の転送用にUNIXドメインソケットを作成し,SSH_AUTH_SOCK環境変数にソケットのパスを設定します。

次に,ssh-addコマンドによって秘密鍵をエージェントに追加します。この状態で,sshコマンドを使ってサーバへログインしようとすると,sshはSSH_AUTH_SOCK環境変数の有無をチェックして,エージェントに登録されている秘密鍵を使って認証します。このとき,sshコマンドでエージェント転送オプションである「-A」オプションを利用しておくと,接続先のサーバでUNIXドメインソケットを作成し,SSH_AUTH_SOCK環境変数をログイン後のシェルに設定します。こうすることで接続先のサーバでも手元で起動したssh-agentに保存された秘密鍵を利用することが可能になります図4⁠。

図4 SSHエージェント転送の例

図4 SSHエージェント転送の例

エージェント転送が期待した動作をしない場合は,まずはエージェントが正しく起動しているか,そしてエージェントに保存されている鍵が何かを確認してみましょう。ssh-addコマンドの「-l」オプションを使うことで,保存されているすべての鍵のフィンガープリントを確認できます。

まとめ

SSHにかかわるコマンドやオプション,設定ファイル,設定項目は決して少なくありませんが,非常によく起きるトラブルに対して押さえておくべき基本的な点について解説しました。もし,すでにSSHに関して何か問題を抱えている場合は,今回の内容が少しでも問題の解決につながれば幸いです。

LinuxやBSDでSSHを使う場合,OpenSSHを使うことがほとんどだと思いますが,OpenSSHは現在もバージョンアップが続けられており,バグフィックスや新機能が多く追加されています。バグによってトラブルが起きている場合はバージョンアップによって解決するかもしれません。新たなトラブルが起きた場合は,sshやsshdのデバッグログを出力して動作を確認することや,manコマンドを活用して各種設定項目の詳細について理解を深めることで解決につながることでしょう。

.ssh/configを有効活用しよう

sshコマンドを使う際,毎回同じオプションやユーザ名,IPアドレスなどを入力するのは無駄が多かったり,オプションの設定漏れなどのトラブルが起きやすいため,$HOME/.ssh/configというsshコマンドで共通に使われる設定ファイルを用意しましょう。設定ファイルには,接続するすべてのサーバ共通のオプション,サーバごとのオプションを定義できます。ここではとくに便利だと思われる設定について触れていきます。

まずは,ForwardAgent。yesを設定すると「-A」オプションと同等で,エージェント転送が有効になります。次にHost。ホスト単位の設定で,ここで定義した名前はsshのホスト名の代替として使うことができます。

たとえば,Host server01と設定した場合は,ssh server01でログインできます。それ以降の行に書いた設定はホストに関する設定となり,次のHostの定義が出現するまで続きます。HostNameはホストのIPアドレスかホスト名を記述,Portはポート番号,Userはログインユーザ名,IdentityFileは秘密鍵ファイルのパスになります。

さらにポートフォワードの設定もできます。LocalForwardで接続先サーバのポートをローカルに転送することができます。DynamicForwardを設定すると接続先のサーバをSOCKS Proxyとして使うことができます。

.ssh/configで設定できる個別の項目について,詳細はここでは詳しく述べませんが,このほかにもいろいろと便利な設定ができます。詳細についてはman ssh_configで確認してみましょう。

Software Design

本誌最新号をチェック!
Software Design 2021年10月号

2021年9月18日発売
B5判/184ページ
定価1,342円
(本体1,220円+税10%)

  • 第1特集
    [MySQL/PostgreSQL/Oracle DB対応]
    データモデリングチェックリスト48
    現場で使える設計のコツ,データの効率化手法
  • 第2特集
    挫折しないOAuth/OpenID Connect入門
    APIを守る認証・認可フローのしくみ
  • 短期連載
    PHPカンファレンス2021通信
    [2]PHP 8で動く!? 非同期処理HTTPサーバ Laravel Octaneを使ってみよう!
  • 短期連載
    GitOpsで作るKubernetesのCI/CD環境
    [最終回]より実践的なGitOpsのために

著者プロフィール

清水勲(しみずいさお)

SI企業を8年間勤めた後,2011年に株式会社ミクシィ 運用部 アプリ運用グルー プにてSNS mixiの運用に携わる。

2014年にスマホアプリ「モンスターストライク」のサーバーチームに加わり,現 在はXFLAG™スタジオ ゲーム開発室 SREグループに所属。

得意分野はLinux,ミドルウェアレイヤー。最近はGoでコードを書くのが好き。 クラフトビールが大好物。

Twitter:@isaoshimizu

バックナンバー

トラブルシューティングの極意―達人に訊く問題解決のヒント

バックナンバー一覧