どっかの高専生の技術備忘録

10割自分の備忘録用のブログ。

RaspberryPiにUbuntuサーバーを入れて公開鍵とGoogle Authenticator使ってSSHするまで

目次

やりたいこと

RaspberryPi 4 Model BにUbuntu Server 22.04を入れて、SSHがしたい。
余裕があれば、ログインに公開鍵とGoogle Authenticatorを用いた2段構えにしたい。 どうせなら、自分なりの自宅内ラズパイSSH鯖の初期設定も書いちゃおう モニタがないので、Windows Terminal上からこれらの設定をしていく。

!注意!

ポート開放をして、外部からSSH出来るようにするHOWTOはこの記事では紹介してません。
ルーターによって設定が異なったり、そもそも契約内容によっては出来なかったりするので、各々調べてみてください。。。m( )m

環境

  • ラズパイ:RaspberryPi 4 Model B
  • SSHするクライアント:Windows 11にデフォで入ってるsshコマンド
  • 入れるOS:Ubuntu Server 22.04 LTS
  • OSイメージ焼くソフト:Raspberry Pi Imager1.7.2

そもそも公開鍵ってなんぞや?って人には。。。

以前、共通鍵暗号方式、公開鍵暗号方式について記事を書きました。
原理は同じなので、公開鍵についてよく知らないって方はこちらの記事を読んでみてください。

Step 0 ~Raspberry Pi Imagerを使ってSDに書き込む~

Raspberry Pi Imager
ホスト名の変更や、WiFiの設定、ユーザー名の設定は右下の歯車から変更できます。
後から、コンソール上で変更も出来ますが、自分は面倒くさがりなので、ここで設定しちゃいます。
下に各設定について書いていきます。

ホスト名

設定すると、mDNSに対応してる環境だと、LAN内ならIP直打ちしなくてもアクセスできるようになります。

SSHを有効化する

今回はSSHのログインに公開鍵認証を使いたいので、ちょこっと詳しく書きます。
1. 鍵ペアの作成
ssh-keygen -t ed25519を叩いて鍵ペアを作ります。
Windows環境だと、C:\Users\ユーザー名\.ssh以下に鍵が生成されます。Linux環境だと、~/.ssh以下に生成されると思います。
2. 公開鍵をautorized_keysに登録
詳細な設定欄から、 SSHを有効化->公開鍵認証のみを許可する->ユーザーhogehogeのためのauthorized_keysに作った鍵ペアの公開鍵を貼り付けてください。
公開鍵は拡張子が.pubになっているものです。間違っても、秘密鍵を登録しちゃだめですよ?
ssh-ed25519 XXXXXXXXXXXXXXXXX hogehoge@HOGEHOGEみたいになってたらそれが公開鍵です。

ユーザー名とパスワードを設定する。

見ての通りユーザー名とパスワードを設定できます。 Ubuntu Serverの場合、何も設定しなくても初回ログインの時にパスワードを変更するように言われますが、ここで設定しちゃうのが楽かもしれないです。

Wi-Fiを設定する

これも見ての通りWi-Fiが設定できます。
今回は有線LANを使う予定なので設定しませんでしたが、チェックを入れた時、PCがどこかしらのアクセスポイントに接続してると自動でSSIDとPWを設定してくれるみたいです。

ロケール設定をする

タイムゾーンの設定をしないと、時刻表記UTCになってしまいます。
また、JISキーボードを使っている人は、ここで設定したほうがいいと思います。

Step 1 ~RaspberryPiの起動と、ログイン~

OSが書き込み終わったらラズパイに電源を投入して、SSHにログインします。
ここからは、以下のようにラズパイの設定をしたと仮定して進めていきます。

ラズパイのIPアドレス:192.168.0.XX
ラズパイのホスト名:hogehoge.local
ユーザー名:hage
作成した鍵ペアのファイル名:id_ed25519, id_ed22519.pub

ラズパイが起動したことを確認したら、早速ログインしていきます。
初回ログインの場合、SSHはデフォルトの22番ポートでリッスンされてるので、
ssh -i C:/Users/ユーザー名/.ssh/raspberry_ed25519 hage@hogehoge.localで接続出来ると思います。
もし、mDNS非対応な環境なら
ssh -i C:/Users/ユーザー名/.ssh/raspberry_ed25519 hage@192.168.0.XXで接続出来ると思います。
初めて接続する時にはこのようにこのホストを信用してもいいか?と聞いてくるので、一応フィンガープリントを確認してyesとタイプしてください。

SSH Login
ログインに成功すると下のSCのように、ラズパイの状態を表示してくれます。
SSH Loged in

小咄~パスワードでSSHにログインしようとどうなるか?~

きちんと、SSHのログインに公開鍵のみ使われているか確認してみると こんな感じに、Permission denied (publickey)となってしまい、PWではログイン出来ないようになっています。

SSH Login Denied

Step 2 ~IPアドレスの固定化~

/etc/netplan/以下にあるyamlファイルを弄れば出来ますが、ルーターの方でも設定が必要なことがあります。
ルーターによって設定が異なると思うので、各自調べてみてください。
sudo nano /etc/netplan/99-netcfg.yamlを叩いてyamlファイルを作ります。
作ったら以下のように書き込んでください

network:
    ethernets:
        アダプタ名:
            dhcp4: false
            addresses: [設定したいIPアドレス/24]
            nameservers:
              addresses: [1.1.1.1,1.0.0.1]
            gateway4: ゲートウェイアドレス
    version: 2
    renderer: networkd

アダプタ名などはip addrコマンドなどを使って調べてみてください。

Step 3 ~SSHのリッスンポートを変更~

ゆくゆくは学校からとかでもSSH出来るようにしたいので、デフォルトの22番ではなく、リッスンポートを適当なものに変更します。
ポート番号は0~65535の中からここに乗っていないものを選びましょう。
もし65535に設定するとしたら /etc/ssh/sshd_configの一番下にこのように追記してください。

#User settings
port 65535

変更したらsudo service sshd restartSSHデーモンを再起動して、設定したポート番号でログイン出来るか試してみてください。
65535番に設定した場合はssh -i C:/Users/ユーザー名/.ssh/raspberry_ed25519 -p 65535 hage@hogehoge.localでログイン出来ると思います。 ちなみに、ポート番号が間違っていると、port 22: Connection refusedのように表示されます。

Step 4 ~ufwを使ってふぁいやーうぉーる

下にチートシートを作ったので、これを参考にして見て下さい。
設定を間違えると、ログインできなくなったりするので、必ず1セッションは残したまま作業してくださいね?

コマンド 内容
sudo ufw enable ufwの有効化
sudo ufw disable ufwの無効化
sudo ufw status 現在設定されているルールとufwの動作状態
sudo ufw default deny ufwホワイトリスト方式で運用する、今回はこっち
sudo ufw defalut allow ufwブラックリスト方式で運用する
sudo ufw allow AAAA AAAAポートへのアクセスを許可する
sudo ufw deny AAAA AAAAポートへのアクセスを拒否する
sudo ufw allow 192.168.0.YY to any port AAAA 192.168.0.YYからAAAAポートへのアクセスを許可する
sudo ufw deny 192.168.0.YY to any port AAAA 192.168.0.YYからAAAAポートへのアクセスを拒否する
sudo ufw delete N N番のルールを削除する

Step 5 ~Google Authenticatorを使って2段階認証~

ここから、Google Authenticatorを使った2段階認証を導入していきます。
目標は公開鍵の認証とGoogle Authenticatorによる6桁コードの入力による、2段階認証です。

0. 対応アプリをDL

Google Authenticatorを使って2FAするので、もちろん対応アプリが必要です。
AndroidならAegis, Google Authenticator, Microsoft Authenticator
iPhoneならGoogle Authenticator, Authy, Microsoft Authenticatorあたりになるかな?
個人的にはAndorid勢ならAegisがおすすめ、Androidの自動バックアップのなかにデータを入れてくれるので、機種変がすんごく楽

1. パッケージの更新とアップグレード

sudo apt update && sudo apt upgradeでパッケージの更新とアップグレードをします。
初めて実行するときは、すごい量のパッケージが更新されていくので気長に待ちましょう。

2. libpam-google-authenticatorのインストール

2段階認証用のPAMモジュールをインストールしていきます。PAMというのは、Linuxのあらゆるログイン処理に関わるモジュールです。
sudo apt install libpam-google-authenticatorちなみに、QRコードを表示させるために、libqrencode4もついでにインストールされます。

3. Google Authenticatorの設定

google-authenticatorを叩いて2段階認証の設定をしていきます。

Do you want authentication tokens to be time-based (y/n)
これは、時間ベースでコードを生成するか?という質問なのでyを入力します。

入力するとこのようにQRコードが表示され上部に画像へのリンク、下に秘密鍵が表示されます。
これをアプリで読み取ったら、Enter from appとなっているところに6桁の番号を入力します。
成功するとこのように、アプリが使えない場合の非常用コード5個が表示され
Do you want me to update your "/home/dtk-qry/.google_authenticator" file? (y/n)と聞かれます。
これは、設定ファイルを書き出すか?と聞いてるので、yを入力します。

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n)

これは、同じコードを複数回使うことを禁止するか?という質問です。yを入れた場合30秒に1回のみのログインになります。
今回は1度に複数のセッションをたてるためにnを入力しました

By default, a new token is generated every 30 seconds by the mobile app.
In order to compensate for possible time-skew between the client and the server,
we allow an extra token before and after the current time. This allows for a
time skew of up to 30 seconds between authentication server and client. If you
experience problems with poor time synchronization, you can increase the window
from its default size of 3 permitted codes (one previous code, the current
code, the next code) to 17 permitted codes (the 8 previous codes, the current
code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
between client and server.
Do you want to do so? (y/n)

これは、アプリとサーバー間で4分の時間のズレを許容するかという質問です。デフォルトは30秒なのでyにしておきました

If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting? (y/n)

これは、3回ログインに失敗すると、この30秒で生成されたコードは無効にするという設定です。
ただ、表示されてる数字を3回も間違えることはないと思うので、yを入力します

4. /etc/ssh/sshd_configの編集

SSHのログインに公開鍵認証とチャレンジレスポンス認証を有効にします。
(Google Authenticatorもチャレンジレスポンス認証の1種になります。)
/etc/ssh/sshd_config/の末尾に以下を追記します

ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive

また62行目付近にある

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
# KbdInteractiveAuthentication no

KbdInteractiveAuthentication no必ずコメントアウトしてください。最悪、ログインできなくなります。(1敗)
これで、SSHのログインに公開鍵(publickey),キーボードからの入力(keyboard-interactive)が求められるようになります。
しかし、このkeyboard-interactiveには自動でパスワードの入力を求める機能がついているので、それを無効化していきます。

5. PAMの設定 /etc/pam.d/sshd

先のパスワードが聞かれちゃう事象とそもそもlibpam-google-authenticatorを使うように設定をしていきます。
/etc/pam.d/sshdの4行目にある

# PAM configuration for the Secure Shell service

# Standard Un*x authentication.
@include common-auth

@include common-authコメントアウトさせます。これで、パスワードの入力を求められなくなります

# PAM configuration for the Secure Shell service

# Standard Un*x authentication.
# @include common-auth

こんな感じ
そうしたら、末尾に以下を追記します

# User settings
auth required pam_google_authenticator.so nullok

nullokGoogle Authenticatorを設定していないユーザーは公開鍵認証のみでログイン出来るようにするためのオプションです。
ちなみに、入力中の6桁コードを表示させたい場合は

# User settings
auth required pam_google_authenticator.so nullok echo_verification_code

のように、echo_verification_codeを追加してあげてください。

6. SSHの再起動

設定を更新するためにsudo service ssh restartSSHを再起動してあげてください

7. SSHにログインする

ここまでの設定がきちんと出来ていれば、このように、2段階認証用の2桁コードが求められます。
コードを入れてログインができれば、完璧です!!

参考にさせて頂いたところ

hana-shin.hatenablog.com

luciferous-report.hatenablog.com