Vaultwardenで家族全員のパスワードセキュリティレベルを激アゲした話

:::note info
現在はWebARENA Indigo(VPS)でインスタンスを建て、Docker上でOIDCWardenとPostgreSQLを稼働させています。
また、メール配信にはMailTrapからExchange OnlineのHVE(大容量メール)に切り替えました。
- WebArena Indigoについて
    - [公式サイト](https://web.arena.ne.jp/indigo/)
    - 選定した理由・メリット
        - 国内ホスティングのVPSとしては自分の知る限りではぶっちぎりの最安値
            - Azure SpotやAmazon Lightsailより安い
        - 1vCPU/1GBRAM/20GBディスクの固定IPv4/v6ありで月額¥449
        - ネットワークのIN/OUT料金は無料、ディスクも料金に含まれている
        - ディスクはすべてSSD(AzureでいうStandard SSD相当?)
    - 欠点・デメリット
        - 他のインスタンスによる影響を受けやすくパケロスが出やすい
        - 追加ディスクは利用できない(インスタンスの拡張によるシステムディスクの拡張は可)
        - インスタンスの拡張は出来るが縮小はできない
- OIDCWardenとは
    - [GitHub](https://github.com/Timshel/OIDCWarden)
    - Timshel氏によるVaultwardenをベースにOIDCによるSSO機能を統合したフォーク
    - マスターパスワードは必要なものの、ID+PWによる認証を廃止し、強制的にIdPを利用させることが可能
:::


# 1. はじめに  
パスワードって、なんで皆使いまわしちゃうんでしょうね。
情報漏洩のリスクは勿論、過去どのサービスを使ったのかすら忘れてしまいます。
自分だけBitwardenの有料プランに加入して2FA含めて管理していましたが、家族の方もどうにかしてやろうと考えた次第です。
今回Vaultwardenを使用した理由は主に3つです。
- 無料であること
- TOTP・Passkeyを管理できること
- 多種多様なクライアントで使用できること
    - PC、ブラウザはもちろんAndroid/iPhoneでも使えます

今回使用するのは次の5つです
- Vaultwarden(Docker)
    - BitwardenのサーバをRustで再実装したOSSです
- 公開用のドメイン
    - 今回の手順ではCloudflareと組み合わせる為、ドメインをお持ちの場合はCloudflare Registrarに移管することをオススメします(ドメインの取得・更新料も安い)
- Cloudflare ZeroTrust
- Dockerが動作出来るマシン(今回はAzureのB1sVM無料枠のUbuntu22.04)
- メール送信の為のSMTPサーバ(今回はMailTrapを使用)

# 2. ひとまずVaultwardenを動かそう
VaultwardenはDockerで動かすのが一番楽です。
今回はAzureを使用して構築します。SSHも面倒なので操作はAzure Portalのシリアルコンソールを使用しています。(コピペも出来るよ)
下記はDockerを一通り導入するためのセットです。
```bash
apt update -y && apt upgrade -y && apt install sudo curl
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
```
次に適当な場所にVaultwarden用のディレクトリを作ります。
自分はルート配下に作りました。
```
sudo mkdir /vaultwarden/
```
次に作ったディレクトリに移動してから`sudo nano docker-compose.yml`
```
version: '3'
services:
  vaultwarden:
    image: vaultwarden/server
    container_name: vaultwarden
    environment:
      - TZ=Asia/Tokyo
      - SIGNUPS_ALLOWED=true
      - VIRTUAL_HOST=vaultwarden.example.com
      - VIRTUAL_PORT=80
      - SMTP_HOST=live.smtp.mailtrap.io
      - SMTP_FROM=noreply-vaultwarden@example.com
      - SMTP_PORT=587
      - SMTP_SECURITY=starttls
      - SMTP_USERNAME=example
      - SMTP_PASSWORD=example
      - SMTP_AUTH_MECHANISM="Login"
    env_file:
        - /vaultwarden/vaultwarden.env
    volumes:
      - /vaultwarden/vw-data:/data
    ports:
      - 80:80
    restart: always
```
SMTPに関してはお好みのものを使用してください。
上記の場合、SMTP周りのusernameとpasswordとその他をちょっと変えればmailtrapですぐ使えます。
次に`sudo nano vaultwarden.env`

```
ADMIN_TOKEN='ここに40文字のランダム文字列とかargon2とか入れる'
```
これで動かす準備はOKです。`sudo docker compose up -d`で立ち上げてcurl http://127.0.0.1 とか見てみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/d861aa1d-6c74-dd44-6f2c-8c1fbe9fdf69.png)
バッチリローカルで動いてます。
動作確認する分にはlocalhostでも良いのですが、外部からアクセスする場合、httpsでないと使えません。
次はCloudflare ZeroTrustを使って安全に公開します。

# 3. Cloudflare ZeroTrustのTunnelでInbound Deny/ポートフォワードなしで公開しよう(勝手に証明書も付くよ！)
CloudflareのポータルからZeroTrust、Access→Tunnelsを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/6ccbb8eb-27eb-cfcd-a655-2063a5708c7c.png)

トンネル名を決め～の(なんでもいいです)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/99bcd567-71c5-d70e-5cb5-5c05ba21811a.png)

トンネルコネクタを入れ～の
(左下をコピペして実行するだけでコネクタのインストールから接続まで勝手にやってくれます)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/65922b53-298e-60de-6929-de80d08d7a3c.png)

どこに繋ぐかを設定し～の(使用するドメインはCloudflareで管理されている必要があります)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/1adfebcd-da00-7dbd-1d63-898138537bb0.png)
今回はAzureを使用しましたが、グローバルIPアドレスを1つ割り振ってVnet外のInboundはAll Denyにしています。(SSHも不可)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/fcf6a774-98b9-da48-d7ee-b11d2b0f6d29.png)
これだけでInboundをAll Denyしていても接続できる非常にけしからんトンネルが完成しました。
設定したサブドメインに対して接続してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/7f8bf26a-d178-b1d3-d661-88d2d15de925.png)
ちゃんと繋がりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/632f0775-8b35-0356-6db1-d6eb2570f64c.png)
Cloudflare Tunnelは勝手にLet`s Encrypt証明書も取ってくれて更新するので手間がかかりません。
ここまでの作業が終わったら、Web版Vaultwardenにアクセスしてアカウントを作成して下さい。
また、Vaultwardenに作成したアカウント自体に2段階認証を設定しておくことをオススメします。

# 4. Adminページで設定変更しよう
`/admin`を開き、vaultwarden.envで設定したAdmin Tokenを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/a8905074-abc5-3bbb-fe6d-05050647d29c.png)
重要なところだけピックアップします。
- General
    - Domain URL →メールや内部に使用されるドメインです。これを変え忘れると、メールのリンク等のドメインがlocalhostになってしまいます。
    - Allow new signups →アカウント作成後はオフにしてください。外部のユーザーがアカウントを作成できてしまいます。
    - Allow invitations →アカウント作成後はオフにしてください。内部のユーザーが外部のアカウント作成に招待できてしまいます。

- SMTP Email Settings→メール送信のための設定です。いい感じにしてください。

上記の設定が完了し、長期間変えることがない事が予想される場合は`Vaultwarden.env`のADMIN_TOKENを消してください。
`/admin`ページへアクセス出来なくなりますので、攻撃リスクを低減できます。
# 5. 今まで使っていたパスワードマネージャー等から引き抜こう
Vaultwardenは、Bitwardenと同じく多種多様なマネージャーからインポートすることが出来ます。
例えば
- 本家Bitwarden
- Chrome(csv) chrome://password-manager/settings
- Firefox(csv) about:logins
- Keepass 2(xml)
- LastPass(csv)
- Safari and macOS(csv)
- 1Password(csv/1pif/1pux)
などなど

Chromeであれば、上記のリンクを開いて`ファイルをダウンロード`を押すだけで簡単にエクスポート出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/1e706219-c5f8-25de-1d77-48e09cdf1e4f.png)
エクスポートしたcsvデータは、Web版Vaultwardenで指定してあげるだけで簡単にインポートできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/2c9ed727-143e-23b2-09f5-86a46960aed2.png)

# 6. 実際に使ってみよう
Chrome、Firefox、MSEdge等は基本的にBitwardenの拡張機能を使用します。
また、スマートフォンではアプリストアからBitwardenのアプリをダウンロードしてください。
https://bitwarden.com/ja-JP/download/
初期設定ではbitwarden.comに対して接続するので、セルフホストに変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/d803fee7-dd3b-3edb-2594-22996b2db1a3.png)
ホスティングしているドメイン名に設定して`保存`を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/af700c3a-5c49-dc6f-c6f2-8b199af3ff03.png)
事前に作成したアカウントのメールアドレスを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/2fe8b04b-b70b-f683-ec02-cc2b721fd93b.png)
マスターパスワードを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/bf275269-0a3a-eb36-7c53-bd4bd99677a0.png)
2段階認証を設定した人はこのタイミングで入力してください。
ログインに成功すれば、保管庫が見えるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/293cf0f6-0360-70d3-f0b0-fd7e24545a59.png)

おすすめの設定は設定→管理→自動入力→ページ読み込み時の自動入力を有効化にチェックです。
これでページを開いた際に、自動でパスワードを入力してくれます。(httpsで入力したパスワードは、httpで警告してくれます)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/4f8253db-6090-9cf1-2d12-b981ae25d28e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/919e49d5-1e82-89f7-db66-e66f47cf2f95.png)

また、TOTPも自動入力時にクリップボードに保存されるのでTOTP入力画面でCtrl+Vするだけでログインできます。

AndroidやiPhoneでも同じ様に`自動入力サービス`の設定を行うことで、自動でパスワードのサジェストをしてくれます。

# 7. セキュリティレベルを激アゲしよう
ここまでは今までとセキュリティレベルは何ら変わりありません。

なのでいままで使用していたパスワードの記録から1つ1つサービスを確認し、今後も使うサービスであれば設定できる最大長かつランダムなパスワード(と2FA)を設定し、Vaultwardenに記憶させます。
今後使用しないサービスであれば、可能であればアカウントを削除したり、削除できない場合は同じく最大長かつランダムなパスワードを設定します。

結果、2時間ほど作業して100近くあったパスワード群は40ほどまで減り、新しくサービスに登録する場合は必ずパスワードマネージャーで生成・登録するように統一できました。
定期的にVaultwarden自体のバックアップも取っているため、万が一VMが壊れた場合でも復旧できるようにしてあります。(パスワード自体は暗号化されているので直接読めません)

# 8. 最後に
今回はできる限りコストを抑えてやってみました。
AzureのVMは無料枠なので1年間はほぼ0円、ドメインも年間1000円程度です。
raspberrypiでも十分動きますし、ポート開放する必要もありません。
ぜひ皆さんもセルフホストしてみてはいかがでしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/7d5e3b5d-ab6d-6456-99eb-707a57d6e922.png)