YubiKeyを使ったSSH公開鍵認証(PIV)

はじめに

前回の投稿「YubiKeyを使ったSSH公開鍵認証(FIDO)」の冒頭で触れた、YubiKey のPKCS #11 準拠のPIV(Smart Card)を使ったSSH公開鍵認証を試してみたので、その手順などを解説します。

PIV を使ったSSHの公開鍵認証

  • PIV とは、FIPS 201 で規格化された個人識別情報を検証するための要件で、米国の政府職員が持つ身分証明用のICカードで使われている標準規格
  • YubiKey にはPIV の機能があり、YubiKey 5 シリーズの場合は公開鍵暗号の秘密鍵とX.509 証明書を格納するスロットが4つある
  • OpenSSH クライアントからYubiKey のPIV にアクセスするために、ミドルウェアとしてOSS のOpenSC をインストールして使う

YubiKeyPIV に格納した公開鍵暗号の秘密鍵を使って、SSHサーバにSSH公開鍵認証で接続します。
YubiKey のPIV は、秘密鍵が外部に漏洩しないようにする対策が施されているので、SSH サーバに登録した公開鍵に対応する秘密鍵が格納されたYubiKey を接続したパソコンからしか、SSH サーバに接続できないようにすることができます。
PIV にはPIN を登録することができ、連続して入力失敗するとロックされるので、万が一YubiKey が第三者に窃取されたとしても、不正ログインは防げる仕組みになっています。

環境

クライアント側の環境

  • MacBook Pro 2022(macOS Monterey 12.4)
  • OpenSSH client (8.6p1) ※macOSにバンドルインストール版 (*1)
  • OpenSC (0.22.0) ※当手順にインストール手順を記載
  • YubiKey Manager
    • GUIツール (1.2.4)
    • CLIツール (4.0.7)
  • YubiKey 5 NFC(Firmware 5.4.3)

(*1) 前回の解説でOpenSSHクライアント をmacOS バンドルインストール版からHomebrew からインストール版に切り替えていたので、元のmacOS バンドルインストール版に戻した

サーバ側の環境

  • Ubuntu 20.04.4 LTS
  • OpenSSH server 8.2p1

クライアント側の環境設定

1. OpenSC のインストール

Homebrew でOpenSC をインストールします。

brew install opensc

OpenSC のインストール先を確認して、OpenSSH のコマンドを実行する際に指定するPKCS #11 のライブラリのパスを確認します。

% brew --prefix opensc
/opt/homebrew/opt/opensc

% ls -l /opt/homebrew/opt/opensc/lib/opensc-pkcs11.so
-rw-r--r--  1 Capybara admin  247120  6  6 21:15 /opt/homebrew/opt/opensc/lib/opensc-pkcs11.so

YubiKey の初期設定

1. YubiKey のPIV のPIN管理

PIV のPIN管理機能では、PINPUKManagement Key の3つを登録できるようになっています。
いずれもデフォルト値が登録されていて変更しないでもPIV の機能を使うことができますが、セキュリティの観点で変更が推奨とされています。

  • PIN
    • 証明書の生成、SSH接続の際に使う
    • PIN の入力を3回連続失敗するとロックされる(回数は変更可能)
    • デフォルト:123456
  • PUK
    • PIN がロックされた際のロック解除で使う
    • PUK の入力を3回連続失敗するとロックされる
    • デフォルト:12345678
  • Management Key
    • 共通鍵暗号の鍵。鍵の種類は3DES、AES(128,192,256)から選択可能
    • デフォルト:010203040506070801020304050607080102030405060708

YubiKey Manager のCLIツール でPIV の状態を確認するコマンドを実行すると、PIN とManagement Key がデフォルトの状態なので”WARNING” と表示されていました。

% ykman piv info
PIV version: 5.4.3
WARNING: Using default PIN!
PIN tries remaining: 3/3
WARNING: Using default Management key!
Management key algorithm: TDES
CHUID:	No data available.
CCC: 	No data available.

YubiKey Manager にはGUIツールとCLIツールの2つあり、どちらを使ってもこの3つを変更できますが、ここではGUIツール を使って変更します。

GUIツールを起動してYubiKey をパソコンに挿入し、メニューの[Applications] > [PIV] > [Configure PINs] をクリックします。

YubiKey Manager(GUI) PIV PIN(未登録)

この画面からPINPUKManagement Key それぞれの変更画面に移り変更します。

YubiKey Manager(GUI) PIV PIN(登録)

PIN を変更します。
Current PIN は”Use default” のチェックをON にし、登録するPIN をNew PINConfirm new PIN の2ヶ所に入力して[Change PIN] をクリックします。
※ PIN は6〜8文字以上のASCII文字

YubiKey Manager(GUI) PIV PUK(登録)

PUK を変更します。
Current PUK は”Use default” のチェックをON にし、登録するPUK をNew PUKConfirm new PUK の2ヶ所に入力して[Change PUK] をクリックします。
※ PUK は6〜8文字以上の英数字

YubiKey Manager(GUI) PIV Management Key(登録)

Management Key を変更します。

  • Current Management Key は”Use default” のチェックをON にします
  • New Management Key は[Generate] をクリックして自動生成します
    • Algorithm を変える場合はドロップダウンで選択してから[Generate] をクリックします(今回はAES256 を選択しました)
    • 自動生成ではなく任意の値を手入力することもできます
  • Protect with PIN のチェックをON にすると、Management Key がPIN で保護され、CLI ツールで鍵ペアや証明書を生成する際にManagement Key ではなくPIN の入力が求められるようになります

※ Management Key は16進数(数字とa〜fの英字)、文字数は固定でAlgorithm の種類により異なる

3つとも変更したので、再度CLI ツールのコマンドを実行してみます。

% ykman piv info
PIV version: 5.4.3
PIN tries remaining: 3/3
Management key algorithm: AES256
Management key is stored on the YubiKey, protected by PIN.
CHUID:	No data available.
CCC: 	No data available.

変更前に表示されていた”WARNING” が表示されなくなりした。

GUI ツールを使ったPIN、PUK、Management Key の登録の解説はここまでです。参考としてCLI ツールのコマンドを載せておきます。

# PIN の変更
ykman piv access change-pin

# PUK の変更
ykman piv access change-puk

# Management Key の変更
ykman piv access change-management-key -a AES256 --protect

鍵の生成〜自己署名証明書の生成

1. 鍵の生成

YubiKey Manager のCLI ツールを使って鍵を生成します。

% ykman piv keys generate -a RSA2048 --touch-policy ALWAYS 9a pubkey.pem
Enter PIN:
 → ここで登録したPIVのPIN を入力

% ls -l
-rw-r--r--  1 Capybara staff   451  6 12 15:15 pubkey.pem

実行したコマンドの解説です。

  • -a RSA2048
    • 生成する鍵の公開鍵暗号の方式
    • RSA2048 以外に、RSA1024, ECCP256, ECCP384 を指定できる
  • –touch-policy ALWAYS
    • スロットにアクセスする際にYubiKey のタッチを常に求める
    • ALWAYS 以外に、DEFAULT, NEVER, CACHED を指定できる
  • 9a
    • 生成した鍵を格納するスロット
    • PIV のスロットは4つあるので、いずれかを指定します
      • Authentication (9a)
      • Digital Signature (9c)
      • Key Management (9d)
      • Card Authentication (9e)
    • 今回はSSH公開鍵認証で使うので9a を指定しましたが、他のスロットでもよいみたいです
  • pubkey.pem
    • カレントフォルダに生成する公開鍵のファイル名

このコマンドで秘密鍵がYubiKey の指定したスロットに、PEM形式の公開鍵ファイルがカレントフォルダに作成されます。

2. YubiKey 内に作成した秘密鍵の確認

YubiKey 内に作成した秘密鍵を確認する方法を調べてみました。

  • CLIツールのykman piv info
    • 表示されない
  • GUIツールの[Applications] > [PIV] > [Configure Certificates]
    • 表示されない
  • CLIツールのykman piv keys export 9a pubkey.pem
    • YubiKey 内の秘密鍵から生成した公開鍵ファイルがカレントフォルダに作成された

どうやら、3つ目のYubiKey 内の秘密鍵から公開鍵をエクスポートする方法しか、確認する方法はないようです。
ちなみに、エクスポートで作成される公開鍵ファイルは、1. 鍵の生成 でカレントフォルダに作成された公開鍵ファイル(PEM形式)と中身が同じでした。

3. 自己署名証明書の生成

YubiKey Manager のCLI ツールを使って自己署名証明書(X.509)を生成します。

% ykman piv certificates generate -d730 -s "Capybara" 9a pubkey.pem
Enter PIN:
 → ここで登録したPIVのPIN を入力
Touch your YubiKey...
 → YubiKey が点滅したらYubiKey をタッチ

実行したコマンドの解説です。

  • -d730
    • 有効期限までの日数(730日)
  • -s “Capybara”
    • Subject の名前
  • 9a
    • 暗号鍵が格納されているスロット。生成した証明書が格納される
  • pubkey.pem
    • 公開鍵のファイル名

このコマンドでYubiKey の指定したスロットに自己署名証明書が作成されます。

4. YubiKey 内に作成した証明書の確認

ykman piv info で証明書の情報が表示されました。

% ykman piv info
PIV version: 5.4.3
PIN tries remaining: 3/3
Management key algorithm: AES256
Management key is stored on the YubiKey, protected by PIN.
CHUID:	3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
CCC: 	No data available.
Slot 9a:
	Algorithm:	RSA2048
	Subject DN:	CN=Capybara
	Issuer DN:	CN=Capybara
	Serial:		410000000000000000000000000000000000000000000055
	Fingerprint:		5f000000000000000000000000000000000000000000000000000000000000ee
	Not before:	2022-06-12 06:17:05
	Not after:	2024-06-11 06:17:05

GUIツールでも証明書の情報が表示されています。

YubiKey Manager(GUI) PIV Certificates(登録済)

X.509 証明書の詳しい情報を確認する場合は下記のコマンドを実行します。

% ykman piv certificates export 9a - | openssl x509 -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            22:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:ac
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=Capybara
        Validity
            Not Before: Jun 12 06:17:05 2022 GMT
            Not After : Jun 11 06:17:05 2024 GMT
        Subject: CN=Capybara
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:d2:6c:c3:87:51:b0:0c:fd:9d:c2:0e:a9:07:4a:
                    〜〜 省略 〜〜
                    18:fd
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha256WithRSAEncryption
         48:51:51:19:45:1f:c3:e0:68:8d:f6:cf:29:ad:4c:17:c0:de:
         〜〜 省略 〜〜
         84:89:d7:65
-----BEGIN CERTIFICATE-----
MIICsjCCAZqgAwIBAgIUIkBNq32J84S20CuA2NToSjyOs6wwDQYJKoZIhvcNAQEL
〜〜 省略 〜〜
XTR5/KdigsWVcH6f8Vo9zQ7fhInXZQ==
-----END CERTIFICATE-----

5. (補足) GUIツールで自己署名証明書を作成

GUIツールを使って作成することもできるので、画面を貼り付けておきます。

YubiKey Manager(GUI) PIV Certificates(登録)

[Applications] > [PIV] > [Configure Certificates] で証明書を作成するスロットを選択して[Generate] をクリック

YubiKey Manager(GUI) PIV Certificates(登録)Step1

“Self-signed certificate” を選択して[Next] をクリック

YubiKey Manager(GUI) PIV Certificates(登録)Step2

Algorithm を選択して[Next] をクリック

YubiKey Manager(GUI) PIV Certificates(登録)Step3

Subject を入力して[Next] をクリック

YubiKey Manager(GUI) PIV Certificates(登録)Step4

[Expiration date] を指定して[Next] をクリック

YubiKey Manager(GUI) PIV Certificates(登録)Step5

[Generate] をクリックするとYubiKey の指定したスロットに証明書が作成されます。

OpenSSH形式の公開鍵ファイル作成〜サーバに公開鍵を登録〜SSH接続

ここからはOpenSSH のコマンドを使った操作になります。

1. OpenSSH形式の公開鍵の作成

OpenSC に同梱されていたPKCS #11 のライブラリを指定して、OpenSSH 形式の公開鍵ファイルを作成します。

# コマンドの実行結果をターミナルに表示してエラーにならないことを確認する
$ ssh-keygen -D /opt/homebrew/opt/opensc/lib/opensc-pkcs11.so 
ssh-rsa AA0000000000000000000000000000000000000000000000000000000000000000000000kd PIV AUTH pubkey
 → エラーにならず公開鍵が出力された

# コマンドの実行結果をファイルに出力する
$ cd ~/.ssh
$ ssh-keygen -D /opt/homebrew/opt/opensc/lib/opensc-pkcs11.so >id_rsa_piv.pub

$ ls -l
-rw-r--r--  1 Capybara staff   397  6 12 15:28 id_rsa_piv.pub

2. 公開鍵をサーバにアップロード&登録

サーバに公開鍵をアップロードします。

scp id_rsa_piv.pub [email protected]:~/

サーバにSSHで接続して、接続ユーザの~/.ssh/authorized_keys公開鍵を登録します。

% ssh [email protected]

$ mkdir ~/.ssh
$ chmod 700 ~/.ssh
$ cat id_rsa_piv.pub >> ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys

3. 公開鍵認証でサーバにSSH接続

SSH の公開鍵認証でサーバに接続できるか確認します。
実行するコマンドでは、OpenSC に同梱されていたPKCS #11 のライブラリを指定します。

$ ssh -I /opt/homebrew/opt/opensc/lib/opensc-pkcs11.so <ユーザ名>@<ホスト名>
Enter PIN for 'Capybara':
 → ここで登録したPIVのPIN を入力
 → YubiKey が点滅したらYubiKey をタッチ

PIN の手入力 + YubiKey をタッチ2要素認証でサーバに接続することができました。
鍵の生成でオプション–touch-policy ALWAYS を指定したのでYubiKey のタッチを求められましたが、このオプションを指定しない場合はPIN の入力のみになります。

4. クライアント側の設定でSSH接続コマンドの簡略化

クライアント側の~/.ssh/config に下記を記述します。

Host *
  HostName <ホスト名>
  User <ユーザ名>
  PKCS11Provider /opt/homebrew/opt/opensc/lib/opensc-pkcs11.so
  IdentitiesOnly no

上記の設定により、-I オプションを省略して接続できるようになります。

% ssh <ユーザ名>@<ホスト名>
Enter PIN for 'Capybara':
 → ここで登録したPIVのPIN を入力
 → YubiKey が点滅したらYubiKey をタッチ

5. パスワード認証を不許可に設定

SSHサーバの設定/etc/ssh/sshd_config でパスワード認証を不許可にすれば、登録した公開鍵を使った 認証しかできなくなります。

PubkeyAuthentication yes

Match User ubuntu
  PasswordAuthentication no
  AuthorizedKeysFile /home/ubuntu/.ssh/authorized_keys

systemctl reload sshd を実行して設定を反映します。

ssh-agent を使う

ssh-agent を使えばssh-agent にPIN を代理入力させて、YubiKey のタッチだけでSSH接続できるようだったので試してみましたが、ssh-agent に秘密鍵を登録するssh-add コマンドでエラーになりました。
エラーの原因や解消する方法が調べても分からなかったので、記録として残しておきます。

1. ssh-agentに秘密鍵の登録(失敗)

% ssh-add -s /opt/homebrew/opt/opensc/lib/opensc-pkcs11.so
Enter passphrase for PKCS#11:
Could not add card "/opt/homebrew/opt/opensc/lib/opensc-pkcs11.so": agent refused operation
 → 登録失敗
  • エラーの原因(仮定)
    • ssh-agent 起動時に参照するライブラリにPKCS #11 のライブラリがホワイトリストに登録されていないことによる
  • ホワイトリストに登録する方法
    • ssh-agent 起動時のパラメータは、/System/Library/LaunchAgents/com.openssh.ssh-agent.plist で定義されている
    • 上記plist ファイルを編集しようとしたが、readonly で更新できなかった(sudo vi で更新不可)
    • macOS Catalina から変更できなくなったという話があるが、解消方法は見つからなかった

以下、参照したサイト。

YubiKey のPIV を無効にする設定

YubiKey Manager にYubiKey のPIV を無効にする機能があったので、こちらもどのように機能するか試してみました。

  • GUIツールとCLIツールのどちらでも無効にすることはできます
  • この設定は前述のPIN の登録をしなくてもできます

1. YubiKey のFIDO を無効にする

GUIツールのメニューの[Interfaces] をクリックします。

YubiKey Manager(GUI) Interfaces PIV(有効)

左のUSB のPIV のチェックをOFF にして[Save Interfaces] をクリックします。

YubiKey Manager(GUI) Interfaces PIV(無効)

CLI ツールでPIV無効になっていることを確認します。

% ykman info
Device type: YubiKey 5 NFC
Serial number: 99999999
Firmware version: 5.4.3
Form factor: Keychain (USB-A)
Enabled USB interfaces: OTP, FIDO, CCID
NFC transport is enabled.

Applications	USB     	NFC
FIDO2       	Enabled 	Enabled
OTP         	Enabled 	Enabled
FIDO U2F    	Enabled 	Enabled
OATH        	Enabled 	Enabled
YubiHSM Auth	Disabled	Disabled
OpenPGP     	Enabled 	Enabled
PIV         	Disabled	Enabled

% ykman config usb --list
OTP
FIDO U2F
FIDO2
OATH
OpenPGP

16行目のPIV のUSB 欄がDisabled になっています。
また、18行目のコマンドの結果にPIV が出力されていないです。

2. PIV が無効の状態でSSH接続を試行

% ssh [email protected]
Enter PIN for 'OpenPGP card (User PIN)':
 → Ctl + C で中止

PIV のPIN ではなくOpenPGP のPIN の入力を求められたので、コマンドを中止しました。
ちなみに、YubiKey のOpenPGP は出荷時まま何も使用していない状態です。

今度はOpenPGP無効にしてコマンドを実行してみました。

% ssh [email protected]
[email protected]: Permission denied (publickey).

PIN の入力を求められることもなくエラーになりました。

この後、再度有効にして接続できるか試したら接続できました。
無効にしてもPIV の登録情報は削除されずに残ります。

参考まで、CLI ツールのPIV を無効・有効にするコマンドを載せておきます。

% ykman config usb -d PIV
Disable PIV.
Configure USB? [y/N]: y
 → 無効になる ※オプション[--disable] も同じ

% ykman config usb -e PIV
Enable PIV.
Configure USB? [y/N]: y
 → 有効になる ※オプション[--enable] も同じ
  • 上記のコマンドを実行するとYubiKey が点滅するのでタップしてみると、OTP のスロットに設定したYubico OTPの44文字が入力され「Error: invalid input」になった。点滅するけれどもタッチは不要です
  • GUIツールを開いた状態でCLIツールで有効・無効を変更してもGUIツールの表示は変わらない。変更をGUIツールの表示に反映するにはGUIアプリの再起動かYubiKey の再接続が必要

あとがき

PIV に関連して、気になっていることを2点記載しておきます。

YubiKey のPIV を使ったMac 本体のログイン

YubiKey のPIV を使ってMac 本体(OS)にログインするということもできるようです。

YubiKey Manager のGUI ツールのPIV の画面にある”Setup for macOS” をクリックして表示される画面に「macOSのアカウントとYubiKey のPIV に登録する証明書を紐づけて、macOS にYubiKey でログインできる」と書かれています。

YubiKey Manager(GUI) PIV Setup for macOS

この画面の[Setup for macOS] ボタンをクリックすると、YubiKey のPIV に必要な秘密鍵と証明書が作成されるようなのですが、上記Yubico のリンク先のページを見るとPIV を使ったMac 本体へのログインは、M1/Apple Silicon CPU では困難なことがあり非推奨となっていました。

M1 Mac users: not recommend

OS にログインできなくなってしまうと困るので、その困難なことが解消されるまでは試すのを保留にしておこうと思います。

マイナンバーカードの公的個人認証AP を使ったSSH公開鍵認証

マイナンバーカードには公的個人認証AP (JPKI-AP)という機能を備えていますが、これはYubiKey のPIV と同じように公開鍵暗号の秘密鍵とX.509 証明書を格納することができるので、これを使ってSSH サーバに公開鍵認証で接続することができるようです。

公的個人認証AP はマイナポータルなど対応しているサイトへのログイン時に利用されるものですが、このような活用方法があるというのはなんか面白いです。

カードリーダーを持っていれば試せるのですが、持っていないので残念です。

参考

YubiKeyを使ったSSH公開鍵認証(FIDO)

はじめに

YubiKey を使ってSSHをセキュアにする方法がYubico の公式サイトに掲載されていました。

簡単に整理すると下記のようなことができるようです。

  • SSHの公開鍵認証 - クライアント側にYubiKey を挿す
    • PIV(Smart Card)※PKCS #11
    • PGP
    • FIDO2 ※OpenSSH 8.2 のFIDO ハードウェア認証機能を使う
  • SSHサーバの2要素認証の実装 - サーバ側にYubiKey を挿す
    • OTP

この中のFIDO2 を使ったSSHの公開鍵認証を試してみたので、その手順などを解説します。

FIDO2 を使ったSSHの公開鍵認証

  • OpenSSH 8.2p1(2020.2.14リリース) でFIDO ハードウェア認証がサポートされた
  • YubiKey 5 などのFIDOデバイスは、OpenSSH に追加された公開鍵暗号方式“ecdsa-sk” と “ed25519-sk” にサポートされている

つまり、ssh-keygen の-t オプションで“ecdsa-sk” または “ed25519-sk” を指定すると、FIDOトークンに紐づいた鍵を生成することができ、その後パソコンにFIDOデバイスが接続されていれば、他の公開鍵暗号方式の鍵と同じように、SSHサーバに接続することができます。
YubiKey の場合、SSHサーバへの接続時にユーザーにYubiKey のタッチを求めて、タッチしたことをユーザーが接続を明示的に許可したこととして扱うようになっています。

だからどう安全なのかというと、第三者が鍵だけを窃取しても、鍵と紐づいているYubiKey が物理的に手元にないと、鍵を窃取した第三者はSSHサーバに接続することはできない、ということになります。

環境

クライアント側の環境

  • MacBook Pro 2022(macOS Monterey 12.4)
  • OpenSSH client
    • macOSにバンドルでインストール (8.6p1)
    • Homebrew でインストール(9.0p1) ※当手順に記載
  • YubiKey Manager
    • GUIツール (1.2.4)
    • CLIツール (4.0.7)
  • YubiKey 5 NFC(Firmware 5.4.3)

サーバ側の環境

  • Ubuntu 20.04.4 LTS
  • OpenSSH server 8.2p1

YubiKey の初期設定

1. YubiKey のFIDO2 のPINを登録

出荷時の状態のYubiKey にはFIDO2 のPIN が登録されていないので、YubiKey Manager を使って登録します。
YubiKey Manager にはGUIツールとCLIツールの2つありますが、どちらを使ってもPIN の登録ができます。
ちなみに、PIN を登録しないと、CLIツール のFIDO 関連のコマンドが下記のように機能してくれませんでした。(コマンドの実行にPIN の入力が必要な2つ目と3つ目のコマンドがエラーになってる)

% ykman fido info
PIN is not set.

% ykman fido access verify-pin
Error: This feature requires having a PIN. Set a PIN first.

% ykman fido credentials list
Error: Credential Management requires having a PIN. Set a PIN first.

ここでは、GUIツール を使ってFIDO2 のPIN を登録します。

GUIツールを起動してYubiKey をパソコンに挿入し、メニューの[Applications] > [FIDO2] をクリックします。

YubiKey Manager(GUI) FIDO2 PIN(未登録)

FIDO2 PIN のところに”No PIN is set” と表示されています。
[Set PIN] をクリックします。

YubiKey Manager(GUI) FIDO2 PIN(登録)

登録するPINNew PINConfirm PIN の2ヶ所に入力して[Set PIN] をクリックします。
PIN は4文字以上の英数字

YubiKey Manager(GUI) FIDO2 PIN(登録済)

元の画面に戻りました。
A PIN is set, 8 retries left” の表示に変わりました。
PIN が登録され、PIN の入力失敗が8回再試行できる状態になっています。
登録したパスワードは忘れないようパスワードマネージャー等に保存しておきましょう

PIN の登録が完了したので、再度CLI ツールのコマンドを実行してみます。

% ykman fido info
PIN is set, with 8 attempt(s) remaining.

% ykman fido access verify-pin
Enter your PIN:
PIN verified.

% ykman fido credentials list
Enter your PIN:

今回はエラーになりませんでした。
コマンドについての簡単な説明を以下、記載しておきます。

  • ykman fido info
    • FIDO2 アプリの状態を表示するコマンド
    • PIN の登録状態、PIN 入力のリトライ回数が表示される
  • ykman fido access verify-pin
    • FIDO2 をサポートするYubiKey の場合、PIN 入力のリトライ回数をリセットするコマンド
    • コマンド実行時にPIN の入力が求められる
    • 他のPIN 入力が必要なコマンドを実行するとPIN のリトライ回数がリセットされるので、このコマンドが役に立つことはなさそう。失敗する時はこのコマンドも実行できないわけで。。
  • ykman fido credentials list
    • FIDO2 アプリの登録情報を一覧表示するコマンド
    • コマンド実行時にPIN の入力が求められる

GUI ツールを使ったPIN の登録の解説はここまでで、
参考まで、CLI ツールのPIN を登録するコマンドを載せておきます。

ykman fido access change-pin -n<設定するPIN>

鍵の生成〜サーバに鍵を登録〜SSH接続

1. macOSにバンドルでインストールされていたOpenSSHを使って鍵を生成(失敗)

ed25519-sk” を指定してssh-keygen を実行します。

% ssh-keygen -t ed25519-sk
Generating public/private ecdsa-sk key pair.
You may need to touch your authenticator to authorize key generation
Key enrollment failed: unknown or unsupported key type

失敗しました。
不明もしくはサポートされていない鍵タイプ” だそうです。

Yubico のDeveloper 向けサイトに「Disabled by Apple on the bundled version of OpenSSH in MacOS as of the last update to this page」という記載が見つかりました。macOS にバンドルされているOpenSSH は“ecdsa-sk” と “ed25519-sk” が無効にされているみたいです。

Apple のDeveloper 向けサイト等に何か情報がないか探しましたが、何も見つかりませんでした。これ以上突っ込まないで先に進みます。

2. Homebrew でインストールしたOpenSSHを使って鍵を生成

Homebrew でインストールしたOpenSSH であれば鍵生成のコマンドを実行できたという情報が見つかったので試してみました。(結論、成功)

Homebrew でOpenSSH をインストールします。

brew install openssh

Homebrew でインストールしたOpenSSH のコマンドにPATH を通します。
~/.zshrc に下記を追記します。
(2022.6.16 削除)

export PATH=$(brew --prefix openssh)/bin:$PATH

source ~/.zshrc を実行して設定を反映します。 (2022.6.16 削除)

Homebrew でインストールしたOpenSSH のコマンドにPATH が通っていることを確認します。(2022.6.16 追記)

% which ssh
/opt/homebrew/bin/ssh

% ls -l $(which ssh)
lrwxr-xr-x  1 Capybara admin  31  6 16 13:49 /opt/homebrew/bin/ssh -> ../Cellar/openssh/9.0p1/bin/ssh

ed25519-sk” を指定してssh-keygen を実行します。
今回は成功したので、作成された鍵ファイルを削除して、追加で幾つかのオプションを付けて再度実行しました。

% ssh-keygen -t ed25519-sk
 → 成功
% rm ~/.ssh/id_ed25519-sk*
 → 鍵を削除

% ssh-keygen -t ed25519-sk -O resident -O application=ssh:Capybara
Generating public/private ed25519-sk key pair.
You may need to touch your authenticator to authorize key generation.
 → ここでYubiKey をタッチ👆
Enter PIN for authenticator:
 → ここで登録したFIDO2のPIN を入力

Enter file in which to save the key (/Users/Capybara/.ssh/id_ed25519_sk):
 → ここで生成する鍵のファイル名を入力(何も入力せずEnterも可)
Enter passphrase (empty for no passphrase):
 → ここで生成する秘密鍵のパスフレーズを入力
Enter same passphrase again:
 → パスフレーズを再度入力
Your identification has been saved in /Users/Capybara/.ssh/id_ed25519_sk
Your public key has been saved in /Users/Capybara/.ssh/id_ed25519_sk.pub
The key fingerprint is:
SHA256:z0xxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxd0 [email protected]
The key's randomart image is:
+[ED25519-SK 256]-+
|        ......   |
|        ......   |
|        ......   |
+----[SHA256]-----+

% ls -l ~/.ssh
-rw-------  1 Capybara staff   525  5 29 16:31 id_ed25519_sk
-rw-r--r--  1 Capybara staff   159  5 29 16:31 id_ed25519_sk.pub

追加したssh-keygen のオプションの簡単な説明を記載しておきます。

  • -O resident
    • 鍵をFIDO 認証器内に保存する
    • このオプションの有無に関係なく、~/.ssh フォルダに鍵ペアは作成される
    • FIDO 認証器内に鍵を保存しておくと、ssh-keygen -K でカレントディレクトリに秘密鍵と公開鍵のファイルを書き出すことができる
  • -O application=ssh:<your-key-name>
    • 生成する鍵の名前を指定する
    • 指定する場合、“ssh:” に続けて任意の名前を指定する必要がある
    • このオプションを指定しない場合、デフォルトの“ssh:” で作成される
    • ここで指定した名前は、CLI ツールで鍵を削除する際に使われる(例:ykman fido credentials delete ‘ssh:Capybara’

-O resident オプションを付けたので、CLI ツールでYubiKey 内に保存された鍵を確認します。

% ykman fido credentials list
Enter your PIN:
ssh:Capybara 0000000000000000000000000000000000000000000000000000000000000000 openssh

-O application オプションで指定した名前が先頭にある行が1行出力されました。
ALLゼロが何なのかよく分かりませんが、とりあえずYubiKey 内に保存されているようです。

3. 公開鍵をサーバにアップロード&登録

サーバに公開鍵をアップロードします。

scp id_ed25519_sk.pub [email protected]:~/

サーバにSSHで接続して、接続ユーザの~/.ssh/authorized_keys公開鍵を登録します。

% ssh [email protected]

$ mkdir ~/.ssh
$ chmod 700 ~/.ssh
$ cat id_ed25519_sk.pub >> ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys

4. 公開鍵認証でサーバにSSH接続

SSH の公開鍵認証でサーバに接続できるか確認します。

% ssh [email protected]
Enter passphrase for key '/Users/Capybara/.ssh/id_ed25519_sk':
 → パスフレーズを入力
Confirm user presence for key ED25519-SK SHA256:z0xxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxd0
 → YubiKey をタッチ👆
User presence confirmed

パスフレーズ + YubiKey をタッチ2要素認証でサーバに接続することができました。

5. パスワード認証を不許可に設定

SSHサーバの設定/etc/ssh/sshd_config でパスワード認証を不許可にすれば、登録した公開鍵を使った 認証しかできなくなります。

PubkeyAuthentication yes

Match User ubuntu
  PasswordAuthentication no
  AuthorizedKeysFile /home/ubuntu/.ssh/authorized_keys

systemctl reload sshd を実行して設定を反映します。

ssh-agent を使う

ついでにssh-agent を使えばパスフレーズはssh-agent が代理入力してYubiKey のタッチだけでSSH接続できるのではと試したら、SSH接続のコマンドでエラーになりました。
使ったSSHクライアントはHomebrew でインストールしたOpenSSH です。
エラーの原因や解消する方法を調べましたが見つからなかったので、記録として残しておきます。

1. ssh-agentに秘密鍵の登録〜SSH接続(失敗)

% ssh-add id_ed25519_sk
Enter passphrase for id_ed25519_sk:
 → ssh-agentへの登録は成功

% ssh [email protected]
sign_and_send_pubkey: signing failed for ED25519-SK "/Users/Capybara/.ssh/id_ed25519_sk" from agent: agent refused operation
 → サーバの接続は失敗

% ssh-add -D
All identities removed.
 → 後片付けとして、ssh-agentの登録を削除

ちなみに、SSHサーバの設定でパスワード認証を不許可にしないでおくと、SSH接続でエラーになるけれどもパスワード入力が求められ、パスワード認証を使ってSSH接続することはできました。

2. keychain関連のオプション

更についでに、ssh-add のkeychain関連のオプションを使ってみたらエラーになりました。不正なオプションとのことです。
そもそも、Homebrew でインストールしたOpenSSH にはkeychain関連のオプションがありませんでした。macOS にバンドルされているOpenSSH 限定のオプションだったようです。

% ssh-add --apple-use-keychain
ssh-add: illegal option -- -
 → 秘密鍵のパスフレーズをキーチェーンに登録しようとしたら失敗

Apple のDeveloper 向けサイトに掲載されているmacOS 10.12.2 (Sierra) のOpenSSH の更新のページに、Keychain とssh-agent の変更について書かれていました。書きっぷりがmacOS に搭載されているOpenSSH の更新と見えなくもないです。
一応リンクを貼っておきます。

YubiKey のFIDO2 を無効にする設定

YubiKey Manager にYubiKey のFIDO2 を無効にする機能があったので、こちらもどのように機能するか試してみました。

  • GUIツールとCLIツールのどちらでも無効にすることはできます
  • この設定は前述のPIN の登録をしなくてもできます

1. YubiKey のFIDO2 を無効にする

GUIツールのメニューの[Interfaces] をクリックします。

YubiKey Manager(GUI) Interfaces FIDO2(有効)

左のUSB のFIDO2 のチェックをOFF にして[Save Interfaces] をクリックします。

YubiKey Manager(GUI) Interfaces FIDO2(無効)

CLI ツールでFIDO2無効になっていることを確認します。

% ykman info
Device type: YubiKey 5 NFC
Serial number: 99999999
Firmware version: 5.4.3
Form factor: Keychain (USB-A)
Enabled USB interfaces: OTP, FIDO, CCID
NFC transport is enabled.

Applications	USB     	NFC
FIDO2       	Disabled	Enabled
OTP         	Enabled 	Enabled
FIDO U2F    	Enabled 	Enabled
OATH        	Enabled 	Enabled
YubiHSM Auth	Disabled	Disabled
OpenPGP     	Enabled 	Enabled
PIV         	Enabled 	Enabled

% ykman config usb --list
OTP
FIDO U2F
OATH
PIV
OpenPGP

10行目のFIDO2 のUSB 欄がDisabled になっています。
また、18行目のコマンドの結果にFIDO2 が出力されていないです。

2. FIDO2 が無効の状態でSSH接続を試行

% ssh [email protected]
Enter passphrase for key '/Users/Capybara/.ssh/id_ed25519_sk':
 → パスフレーズを入力
Confirm user presence for key ED25519-SK SHA256:z0xxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxd0
sign_and_send_pubkey: signing failed for ED25519-SK "/Users/Capybara/.ssh/id_ed25519_sk": device not found
[email protected]: Permission denied (publickey).

パスフレーズの入力後にエラーになりました。

この後、再度有効にして接続できるか試したら接続できました。
無効にしてもFIDO2 の登録情報は削除されずに残ります。

参考まで、CLI ツールのFIDO2 を無効・有効にするコマンドを載せておきます。

% ykman config usb -d FIDO2
Disable FIDO2.
Configure USB? [y/N]: y
 → 無効になる ※オプション[--disable] も同じ

% ykman config usb -e FIDO2
Enable FIDO2.
Configure USB? [y/N]: y
 → 有効になる ※オプション[--enable] も同じ
  • 上記のコマンドを実行するとYubiKey が点滅するのでタップしてみると、OTP のスロットに設定したYubico OTPの44文字が入力され「Error: invalid input」になった。点滅するけれどもタッチは不要です
  • GUIツールを開いた状態でCLIツールで有効・無効を変更してもGUIツールの表示は変わらない。変更をGUIツールの表示に反映するにはGUIアプリの再起動かYubiKey の再接続が必要

3. FIDO2 が無効の状態でTwitter のログインを試行

以前の投稿「YubiKeyでTwitterアカウントを保護する」でセキュリティキーを使った2段階認証の設定をしていたので、このYubiKey の有効・無効の影響を試してみました。

Yubico のサイトにはTwitter はFIDO2U2F がサポートされていると書かれていました。

Twitter Security protocol support (U2F FIDO2)

実際に試した結果は下記の通りです。

FIDO2FIDO U2Fログイン試行の結果
無効有効ログイン成功
有効無効ログイン成功
有効有効ログイン成功
無効無効ログイン失敗

FIDO2FIDO U2F の両方を無効にした場合のみログインに失敗しました。
振る舞いとしては、1段階目のパスワード入力後、2段階目でパソコンに挿入したYubiKey が点滅せず、タップしても無反応でした。

ちなみに、前述のFIDO2 の登録情報を確認するykman fido credentials list を実行すると、ssh-keygen -t ed25519-sk -O residentで作成した鍵は表示されますが、Twitter の情報は表示されませんでした。
Yubico の下記リンク先に書かれていることが関係していそうな雰囲気があります。(セキュリティ観点で表示されないようにファームウェアがアップデートされた?)
表示されない理由が分かっても解消する訳ではなさそうなので深掘りするのは止めておきます。

参考

Macのssh-agent

Macssh-agentキーチェーンとの連携ができるので、上手く使いこなすと便利そうですが、仕組みがあまりよく分からないで使うのも気持ち悪かったので整理してみました。

はじめに

1. ssh-agentについて

  • OpenSSH の認証エージェント
  • macOS はLeopard から標準インストールされている
  • SSH の公開鍵認証で使う秘密鍵をssh-agent に登録すると、サーバにSSH で接続する際のパスフレーズの手入力を省略できる(ssh-agent が代理でパスコードを入力してくれる)
  • OS をシステム終了するとssh-agent の登録情報が削除されるので、OS を起動する度に再登録が必要

2. キーチェーンの役割について

  • SSH の公開鍵認証で使う秘密鍵のパスコードをキーチェーンに登録すると、登録した秘密鍵をパスコード付きでssh-agent に読み込むことができる
  • キーチェーンには秘密鍵のパスフレーズが保存される(秘密鍵自体は保存されないので、キーチェーンから秘密鍵の復元はできない)

環境について

クライアント側の環境

  • macOS Monterey

サーバ側の環境

  • Ubuntu 20.04.4 LTS

準備

1. SSHの公開鍵認証で使う鍵の作成

今回、鍵の形式はEd25519 で作成します。
作成する際にパスフレーズの入力を求められるので、任意の文字列を指定します。

ssh-keygen -t ed25519
→ パスフレーズを入力する
ls -l ~/.ssh/
→ ~/.ssh/に秘密鍵「id_ed25519」と公開鍵「id_ed25519.pub」が格納されている
  • id_ed25519
    • クライアント側で署名に使う秘密鍵
  • id_ed25519.pub
    • サーバ側で検証に使う公開鍵

2. 接続先のサーバに公開鍵を登録

下記のコマンドで指定したサーバ・ユーザの ~/.ssh/authorized_keys に公開鍵を登録します。

ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]

※ サーバ「test.example」の「/home/ubuntu/.ssh/authorized_keys」に登録されます

3. 接続確認

SSH の公開鍵認証でサーバに接続できるか確認します。

ssh -i ~/.ssh/id_ed25519 [email protected]
→ パスフレーズを入力して接続に成功
exit

ちなみに、オプション-i で秘密鍵を指定しなくても同じ様に接続できました。

ここまでは、ssh-agent を使わないSSH の公開鍵認証です。

ssh-agentを使う

ssh-agent に秘密鍵を登録してSSH の公開鍵認証でサーバに接続します。

1. 秘密鍵をssh-agentに登録

ssh-add ~/.ssh/id_ed25519
→ パスフレーズを入力して登録する

ちなみに、秘密鍵を指定しなくても同じ様に登録できました。
その場合、~/.ssh/ に複数の秘密鍵のファイルがあると、全ての秘密鍵のパスフレーズの入力を求められ登録しようとします。

2. 秘密鍵がssh-agentに登録されていることを確認

ssh-add -l
→ 登録されている秘密鍵に対応する公開鍵のフィンガープリントが表示される

3. 接続確認

パスフレーズを入力しないでサーバに接続できるか確認します。

ssh -i ~/.ssh/id_ed25519 [email protected]
→ パスフレーズの入力を求められずに接続に成功
exit

パスフレーズを入力しないで接続できたということは、ssh-agent が代理でパスフレーズを入力してくれたということになります。

続けて、オプション-i で秘密鍵を指定しないで接続できるか確認します。

ssh [email protected]
→ パスフレーズの入力を求められずに接続に成功
exit

こちらも同じ様にパスフレーズを入力しないで接続できました。

以降、パソコンのシステムを終了するまでパスフレーズの入力が求められなくなるので、便利ではありますがパスフレーズを知らない第三者もこのコマンドを入力するだけでサーバにSSH 接続できてしまうので、離席する際はパソコンをロックする等の運用上の配慮が必要になります。

キーチェーンを使う

秘密鍵のパスフレーズをキーチェーンに登録し、登録したキーチェーンのパスフレーズをssh-agent に読み込んでSSH の公開鍵認証でサーバに接続します。

1. 秘密鍵のパスフレーズをキーチェーンに登録

ssh-add --apple-use-keychain ~/.ssh/id_ed25519
→ パスフレーズを入力して登録する
  • オプション-K非推奨となり、替わりに–apple-use-keychain が用意されていました
  • 引数の秘密鍵の指定を省略すると、~/.ssh/ に格納されている全ての秘密鍵の登録を試みます(各鍵のパスフレーズを聞かれるので、入力して正しければ登録されます)
  • 上記のコマンドを実行すると、ssh-agent にも秘密鍵が登録されました

2. キーチェーンに登録されていることを確認

キーチェーンアクセスで秘密鍵のパスフレーズがキーチェーンに登録されていることを確認します。

キーチェーンアクセスを開き、右上の検索窓に”SSH” と入力して一覧の表示を絞り込むと、登録した秘密鍵が表示されます。

キーチェーンアクセス(一覧)
キーチェーンアクセス(一覧)

一覧の秘密鍵の行をクリックして詳細画面を開き、[パスワードを表示] のチェックをONにすると秘密鍵のパスフレーズが表示されます。

キーチェーンアクセス(詳細)
キーチェーンアクセス(詳細)

3. ssh-agentに登録されている秘密鍵を削除

キーチェーンの秘密鍵をssh-agent に読み込むので、前述「1. 秘密鍵をssh-agentに登録」でssh-agent に登録した秘密鍵を一旦削除します。

ssh-add -D

4. キーチェーンの秘密鍵をssh-agentに読み込む

ssh-add --apple-load-keychain ~/.ssh/id_ed25519
  • オプション-A非推奨となり、替わりに–apple-load-keychain が用意されていました
  • 引数の秘密鍵の指定を省略すると、キーチェーンの全ての秘密鍵がssh-agent に読み込まれます(パスフレーズの入力が求められずに読み込まれます)

5. 秘密鍵がssh-agentに登録されていることを確認

ssh-add -l
→ 登録されている秘密鍵に対応する公開鍵のフィンガープリントが表示される

6. 接続確認

パスフレーズを入力しないでサーバに接続できるか確認します。

ssh [email protected]
→ パスフレーズの入力を求められずに接続に成功
exit

設定

~/.ssh/config

任意でssh-agent に関係する下記のオプションを指定することができます。

Host *
 AddKeysToAgent yes
 UseKeyChain yes
  • AddKeysToAgent
    • サーバにSSHで接続した際に、秘密鍵をssh-agentに登録する設定
    • yes:登録する、no:登録しない(デフォルト)、他にconfirmとaskが指定できる
    • yesにすると、ssh-add を実行する必要がなくなる
  • UseKeyChain
    • サーバにSSHで接続した際に、秘密鍵をキーチェーンに登録する設定
    • yes:登録する、no:登録しない(デフォルト)
    • yesにすると、ssh-add –apple-use-keychain を実行する必要がなくなる

どう使うか

秘密鍵のパスフレーズをキーチェーンで管理して使う

以下の手順でssh-agent を使う

  1. 公開鍵認証で使う鍵を作ったタイミングで秘密鍵をキーチェーンに登録する
    • ssh-add –apple-use-keychain ~/.ssh/id_ed25519パスコードを入力
  2. SSH でサーバに接続する前にキーチェーンの秘密鍵をssh-agent に登録する
    • ssh-add –apple-load-keychain
  3. SSH でサーバに接続する

OS を起動する度に2.を実行する必要がありますが、普段はパスコードの手入力が必要なくなるというのが利点としてあります。
非推奨になったオプション-A に比べると–apple-load-keychain が覚えづらいのが残念な感じです。
この使い方であれば、config の設定は必要なさそうです。

秘密鍵のパスフレーズをキーチェーンで管理しないで使う(configの設定なし)

以下の手順でssh-agent を使う

  1. SSH でサーバに接続する前に秘密鍵をssh-agent に登録する
    • ssh-addパスコードを入力
  2. SSHでサーバに接続する

OS を起動する度にパスコードの手入力が必要なので、パスコードの運用が雑になりそうです。
普段からssh-add コマンドを使うのでssh-agent を意識するシンプルな使い方という感じです。

秘密鍵のパスフレーズをキーチェーンで管理しないで使う(configの設定あり)

以下の手順でssh-agent を使う

  1. config にSSH 接続の際に秘密鍵をssh-agent に登録する設定をする
    • AddKeysToAgent yes
  2. SSH でサーバに接続する(OS 起動後の初回)
  3. SSH でサーバに接続する(2回目以降)

OS を起動する度にパスコードの入力が必要なので、パスコードの運用が雑になりそうです。
普段は ssh コマンドだけを使えばよくなるので、ssh-agent を意識しなくなりそうです。

あとがき

Macssh-agentについて整理できたようで整理できていない感じですが、どう使うかの選択肢は整理できたと思います。
最後に感想とメモのようなものを書き残しておきます。

  • ssh-add のキーチェーンを扱うオプションについて
    • macOS Monterey で-K と-A が非推奨になったらしい
    • 新しい–apple-use-keychain と–apple-load-keychain 覚えづらい
  • config のUseKeyChain について
    • 秘密鍵は基本的に意識して扱いたいので、無意識で永続的に保存される仕組みは使いたくない(sshコマンドの実行でキーチェーンに登録したくない)
  • キーチェーンに登録するのは秘密鍵の保存場所とパスコードの情報
    • ~/.ssh/ の秘密鍵を削除するとキーチェーンに登録されている情報はゴミになる
    • キーチェーンから秘密鍵を復元できない
  • ssh-agent を使わないという選択
    • 離席する際のパソコンのロックが徹底できないのであれば使わない方がよい
    • ssh-agent はあくまでも利便性を向上させるツールなので無理して使うことはない
  • 秘密鍵のパスコードを絶対第三者に使われたくない
    • パスコードをキーチェーンで管理すれば、ウェブサイト向けのパスワードマネージャー(1Passwordなど)のような感覚でパスコードをセキュアに扱うことができる
  • ssh-agent のプロセス起動
    • OS を起動した状態ではssh-agent が起動していない
    • ssh コマンドやssh-add コマンドを実行するとssh-agent が起動する(ps aux | grep ssh-agent で確認)
  • シェル起動時にssh-agent に登録する
    • キーチェーンに登録して、~/.zshrc にssh-add –apple-load-keychain を記述する
    • ssh コマンドでパスフレーズの入力を求められずに接続できる
    • 普段ssh-agent とパスフレーズを全く意識する必要がなくなり利便性はmax

参考

OpenSSHサーバでSSH,SCP,SFTP

OpenSSHサーバを使ったSFTP について書きましたが、SSHSCP について何も書いていなかったので一応書いておきます。

環境について

サーバ側の環境

  • Ubuntu

クライアント側の環境

  • macOS Monterey

OpenSSHサーバの環境構築

OpenSSHサーバのインストール

sudo apt install openssh-server

ファイアウォール

SSHの標準ポート22/TCPを開ける

sudo ufw allow ssh

コマンドの実行後の状態を確認する

sudo ufw status verbose
→ 下記の2つが追加されている
  22/tcp (OpenSSH)           ALLOW IN    Anywhere
  22/tcp (OpenSSH (v6))      ALLOW IN    Anywhere (v6)

OpenSSHサーバの設定

設定ファイルの編集

sudo vi /etc/ssh/sshd_config

/etc/ssh/ssh_config ではなく/etc/ssh/sshd_config

設定した内容(一部抜粋)※既存の設定の変更やコメントアウトなど

AllowTcpForwarding no
X11Forwarding no
Subsystem sftp  /usr/lib/openssh/sftp-server
  • Subsystem sftp はSFTP を使えないようにしたい場合は、コメントアウトする
  • Chroot でSFTPサーバを構築する場合は、Subsystem sftp/usr/lib/openssh/sftp-server ではなくinternal-sftp を指定する→「OpenSSHサーバでSFTP」参照
  • ちなみに、Subsystem sftp/usr/lib/openssh/sftp-server でもChroot なSFTPができてしまいましたが、internal-sftp を指定するのが正しいようです

設定の有効化

OpenSSH サーバを再起動

sudo systemctl restart sshd

接続確認(SSH, SCP, SFTP)

ネットワークを経由しない、サーバ内のローカル接続による接続確認です。

ssh ubuntu@localhost
→ 接続に成功
exit

echo "testdata" > testfile.txt
mkdir temp
scp testfile.txt ubuntu@localhost:temp
ls temp
→ testfile.txt が格納されている
rm temp/testfile.txt

sftp ubuntu@localhost
put testfile.txt temp/
ls temp
→ testfile.txt が格納されている
rm temp/testfile.txt
quit

接続確認(クライアントからサーバ)

サーバは、前述のローカル接続による接続確認をした後の状態で行います。
なので、/home/ubuntu にtemp ディレクトリが作られていて、中にファイルがない状態です。

接続確認(SSH)

ssh ubuntu@<hostname またはipaddress>
→ 接続に成功
exit

接続確認(SCP)

echo "testdata" > testfile.txt
scp testfile.txt ubuntu@<hostname またはipaddress>:temp

scp ubuntu@<hostname またはipaddress>:temp/testfile.txt ./testfile1.txt
ls testfile1.txt
→ testfile1.txt が格納されている
rm testfile1.txt

接続確認(SFTP)

sftp sftpuser@<hostname またはipaddress>
put testfile.txt temp/
ls temp
→ testfile.txt が格納されている
rm temp/testfile.txt
quit

あとがき

単にOpenSSHサーバを使ってSSH、SCP、SFTP を使える状態にするのは簡単にできました。

ただ、サーバを安全に管理する上では運用面をしっかりする必要がありそうです。
例えば、開発したコンテンツのアップロードだけを行う要員には、Chroot でアクセスできる範囲を制限したSFTPしか使えないユーザを割り当てるなど。

今回ははじめにのようなことを書きたかったので、この辺にしておきます。

OpenSSHサーバでSFTP(公開鍵認証)

直前の投稿「OpenSSHサーバでSFTP」の続きです。
前回はパスワード認証だったので、今回は公開鍵認証でユーザ認証できるようにします。

環境について

※ 前回と同じ、サーバはUbuntu を使っています。

クライアントの環境構築

キーペアの生成

公開鍵認証で使うデジタル署名Ed25519のキーペアを生成

ssh-keygen -t ed25519
→ Your identification has been saved in /Users/xxx/.ssh/id_ed25519
   Your public key has been saved in /Users/xxx/.ssh/id_ed25519.pub
  • 任意のパスフレーズを設定します
  • 生成されるキーペアは、id_ed25519 が秘密鍵、id_ed25519.pub が公開鍵
  • キーペアのファイル名を指定したい場合は、-f オプションを使って指定します(今回は指定しなかったのでデフォルトの”id_ed25519″で作成されました)

公開鍵をサーバにアップロード

前回設定したSFTP(パスワード認証)を使ってアップロードします。
※ 公開鍵 id_ed25519.pub/var/sftp/sftpuser にアップロードします。

sftp sftpuser@<hostname またはipaddress>
→パスワードを入力してユーザ認証

cd sftpuser
put ~/.ssh/id_ed25519.pub
quit

OpenSSHサーバの環境構築

前回作成したユーザ「sftpuser」のユーザ認証の方式をパスワード認証から公開鍵認証に変更します。

公開鍵の設置

SSH接続できるユーザでサーバにSSH接続して、公開鍵を設置します。

su - sftpuser
mkdir ~/.ssh
chmod 700 ~/.ssh
cat /var/sftp/sftpuser/id_ed25519.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
exit

sudo rm /var/sftp/sftpuser/id_ed25519.pub

OpenSSHサーバの設定

設定ファイルの編集

sudo vi /etc/ssh/sshd_config

設定した内容(一部抜粋)

PubkeyAuthentication yes
AllowTcpForwarding no
X11Forwarding no
Subsystem sftp  internal-sftp

Match User sftpuser
    ChrootDirectory /var/sftp
    ForceCommand internal-sftp
    PasswordAuthentication no
    AuthorizedKeysFile /home/sftpuser/.ssh/authorized_keys
  • PasswordAuthentication no により、パスワード認証ができないようにする
  • AuthorizedKeysFile で公開鍵を指定する

設定の有効化

OpenSSH サーバを再起動

sudo systemctl restart sshd

接続確認(クライアントからサーバ)

SFTP接続の確認(成功)

Mac のターミナルを使ってネットワーク経由でSFTP接続の確認

echo "test" > testfile.txt

sftp -i ~/.ssh/id_ed25519 sftpuser@<hostname またはipaddress>
→パスフレーズを入力して公開鍵認証

cd sftpuser
put testfile.txt
ls
quit

SSHとSCP接続の確認(失敗)

SSHの接続を試してみると失敗します

ssh -i ~/.ssh/id_ed25519 sftpuser@<hostname またはipaddress>
→パスフレーズを入力して公開鍵認証
→ This service allows sftp connections only.

SCPの接続を試してみると失敗します

scp -i ~/.ssh/id_ed25519 testfile.txt sftpuser@<hostname またはipaddress>:
→パスフレーズを入力して公開鍵認証
→ This service allows sftp connections only.

あとがき

パスワード認証の場合、パスワードが漏洩すると第三者がログインできてしまいますが、公開鍵認証はクライアント上に保存した暗号鍵とパスフレーズの両方が第三者の手に渡らなければ第三者によるログインが成功しないので、より安全なユーザ認証の方式といえると思います。

設定がパスワード認証に比べると面倒かもしれませんが、なるべく公開鍵認証を使うようにした方がよいのでしょう。

OpenSSHサーバでSFTP

クライアント上のファイルをサーバにSFTPでアップロードできるようにします。
今回解説する手順は、SFTP専用のユーザを作成して、Chrootにより限定された場所にファイルをアップロードできるようにする手順となります。

環境について

サーバ側の環境

  • Ubuntu
  • OpenSSHサーバ ※インストール済み

クライアント側の環境

  • macOS Monterey

OpenSSHサーバの環境構築

SFTP専用ユーザーの作成

sudo adduser sftpuser

ユーザ認証はパスワード認証を使うので、任意のパスワードを設定します。
※ 公開鍵認証も可能ですが、SFTP中心の解説にしたいので省略します。

SFTP専用グループの作成

sudo groupadd sftponly

ユーザをグループに追加 ※セカンダリグループ

sudo adduser sftpuser sftponly

SFTP専用ディレクトリの作成

SFTP専用ディレクトリの作成 ※Chrootディレクトリ

sudo mkdir /var/sftp
sudo chown root:root /var/sftp

SFTP専用ユーザのディレクトリの作成 ※ここにアップロードする

sudo mkdir /var/sftp/sftpuser
sudo chown sftpuser:sftponly /var/sftp/sftpuser
sudo chmod 755 /var/sftp/sftpuser

OpenSSHサーバの設定

設定ファイルの編集

sudo vi /etc/ssh/sshd_config

/etc/ssh/ssh_config というファイルもあるけれども、設定するのは/etc/ssh/sshd_config

設定した内容(一部抜粋)※既存の設定の変更やコメントアウトなど

AllowTcpForwarding no
X11Forwarding no
Subsystem sftp  internal-sftp

設定した内容 ※末尾に追記

Match User sftpuser
    ChrootDirectory /var/sftp
    ForceCommand internal-sftp
    PasswordAuthentication yes
  • ChrootDirectory は、SFTP接続した際のルートディレクトリを/var/sftp に設定する
  • ForceCommand internal-sftp により、SFTP の利用に限定する(SSHとSCPが使えない)
  • ChrootDirectoryForceCommand internal-sftp の両方を設定することでChroot とSFTP 限定が有効になるようです

設定の有効化

OpenSSH サーバを再起動

sudo systemctl restart sshd

接続確認

サーバのローカル環境上でのSFTP接続の確認

sftp sftpuser@localhost

接続確認(クライアントからサーバ)

SFTP接続の確認(成功)

Mac のターミナルを使ってネットワーク経由でSFTP接続の確認

echo "test" > testfile.txt

sftp sftpuser@<hostname またはipaddress>
→パスワードを入力してユーザ認証

pwd
→ Remote working directory: /
put testfile.txt
→ remote open("/testfile.txt"): Permission denied
cd sftpuser
put testfile.txt
ls
quit
  • 接続した時点のカレントディレクトリは/var/sftp がルートディレクトリとなっていて、ディレクトリの所有者とグループがroot なのでput でファイルをアップロードしようとすると失敗します。
  • cd でカレントディレクトリを/var/sftp/sftpuser に変えてからput するとアップロードが成功します。

SSHとSCP接続の確認(失敗)

SSHの接続を試してみると失敗します

ssh sftpuser@<hostname またはipaddress>
→ This service allows sftp connections only.

SCPの接続を試してみると失敗します

scp testfile.txt sftpuser@<hostname またはipaddress>:
→ This service allows sftp connections only.

あとがき

ChrootDirectory/var/sftp としましたが、ユーザのホームディレクトリ/home/sftpuser を指定してもよさそうです。

SFTPでファイルのアップロード・ダウンロードをするのが専用のユーザなので、SSH接続できるユーザがそのファイルのコピー等をするのにどこが運用上望ましいかで判断する感じでしょうか。