0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ラズパイ上のわんこ監視システムをBasic+JWT認証からMFA(多要素認証)に変えます

0
Posted at

1.はじめに

ID、パスワードだけでの認証では心許ないので、わんこ監視システム(nginx+Mjpg-streamer)からのストリーミング参照できるデバイスを限定する目的でJWT認証も採用したのですが、各デバイス上でトークンを定期的に更新するのが少々面倒になりました。
それで、安直に多要素認証にすれば、堅牢性と運用上の利便性が両立可能かなと考えました。
今にして思えば、JWT認証は実装で結構苦戦したので、最初からMFAにしておけばよかっただけかと思います。

2.認証用に何を使用する?

この辺の知見ないので、Google AIモード(以降、AIと略す)で今のシステムに合うものを聞いてみたら、リスト上の一番上に(イチオシとして)autheliaを紹介されたので、比較検討することもなくauthelia導入に決定しました。

3.導入方法は?

これまたAIに聞いてみたら、以下を答えてくれたので、AI畜よろしくただ従うのみと。
なお、以降の記載は、まだ家内LANで使用可能な範囲の実装です。
屋外からインターネットを介して利用するにはnginxの設定が不足しています。
また、誤りがあったら申し訳ありません。自己責任でお願いします。

man_202605061120.jpeg

(1)Docker環境の準備: ラズパイにDockerとDocker Composeをインストールします。

(2)Autheliaの配置: Docker ComposeでAutheliaコンテナを立ち上げ、ユーザー情報(ID/パスワード)をYAMLやデータベース(SQLite/MariaDB等)で管理するよう設定します。
(3)リバースプロキシの設定: Nginx等の設定ファイルで、特定のエンドポイントへのアクセスをAutheliaの認証ポータルへリダイレクトするように書き換えます。
 (a)Nginxの各locationブロックにauth_request /authelia;を追加します。
 (b)未認証の場合はAutheliaのログインページ(MFAを含む)へリダイレクトさせます。
 (c)認証の委譲: 認証自体はNginx/Autheliaで完了しているため、Mjpg-streamer等でJWTを検証する必要はなくなります。
 (b)ユーザー情報の取得: Autheliaが認証成功後に、Remote-UserやRemote-GroupsといったHTTPヘッダーにユーザー情報を載せてMjpg-streamer等に転送するようにNginxを設定します。
(4)MFAの有効化: Autheliaのポータル上でTOTP(QRコードスキャン)を設定し、ログイン時に2要素目を要求するようにポリシーを設定します。

3.1 DockerとDocker-Composeの導入

# Dockerのインストールスクリプトを実行
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# 現在のユーザーをdockerグループに追加(次回ログインからsudo不要に)
sudo usermod -aG docker $USER

# Docker Compose プラグインのインストール
sudo apt-get update
sudo apt-get install -y docker-compose-plugin

3.2 Autheliaの導入

Autheliaの動作には主に3つのファイルが必要となる。
最初に設定ファイルを管理するためのフォルダを作成する。

mkdir -p ~/authelia/config
cd ~/authelia
/home/(ユーザー名)/
  └── authelia/
      ├── docker-compose.yml
      └── config/
          ├── configuration.yml
          └── users_database.yml

① docker-compose.yml

services:
  authelia:
    image: authelia/authelia:latest
    container_name: authelia
    volumes:
      - ./config:/config
    networks:
      - auth-net
#    expose:
#      - 9091
    ports:
      - "9091:9091"
    restart: unless-stopped
    environment:
      - TZ=Asia/Tokyo

networks:
  auth-net:
    external: true # 事前に docker network create auth-net が必要

② config/configuration.yml (基本設定)

# ランダム文字列の生成
LC_ALL=C tr -dc 'A-Za-z0-9' </dev/urandom | head -c 64 ; echo

上記コマンドを3回実行し、各々の出力内容を、以下の"適当な長い文字列#1〜#3"に設定する。

server:
  address: 'tcp://:9091/'
jwt_secret: '適当な長い文字列#1'
default_2fa_method: 'totp'
authentication_backend:
  password_reset:
    disable: true # ラズパイ環境なら最初は無効が楽です
  file:
    path: /config/users_database.yml
session:
  name: 'authelia_session'
  secret: '適当な長い文字列#2' 
#  default_cookie_attributes:
#    insecure: true   # HTTPでのCookie送信をブラウザに許可させる
#    same_site: 'lax' # IPアドレス直叩き時のCookie動作を安定させる
  cookies:
    - domain: '192.168.x.xx'
      authelia_url: 'https://192.168.x.xx'
storage:
  local:
    path: /config/db.sqlite3
  encryption_key: '適当な長い文字列#3' 
notifier:
  filesystem:
    filename: /config/notification.txt # 2FA登録用URLがここに書き込まれます
access_control:
  default_policy: 'two_factor' # 全てにMFAを強制

③ config/users_database.yml (ユーザー定義)

# パスワードハッシュ生成コマンド
docker run --rm authelia/authelia:latest authelia hash-password "your_password"

上記コマンドで生成したパスワードを下記password:欄に貼り付ける。

users:
  your_username:
    displayname: "User Name"
    password: "$argon2id$v=19$m=65536,t=3,p=4..." 
    email: user@example.com
    groups:
      - admins

4.Autheliaの起動

# ネットワークを作成して起動
docker network create auth-net #①
docker compose down #②
docker compose up -d

①を実行すると、長い16進文字列が出力されるが、Dockerが作成した「ネットワークID」 で、特に記録などは不要である(出力目的は各人で調べてほしい、もしかすると使用機会があるかも)。
②が必要かどうかは、よくわからない(なくてもよいかも)。

5.Nginxの導入

いろいろな方が導入記事を書かれているので、そちらを参照ください。

6.Nginxの設定

/etc/nginx/sites-enabled/xxx を修正するが、これはシンボリックリンクファイルで、実体は/etc/nginx/sites-available/xxx。
新規インストール直後でsites-enabled下に何もない状態の場合、先にsites-available下に実体ファイルを作成してから、sites-enabled下にシンボリックリンクを作成することになる。
なお、xxxに付与する名称は各人の目的に合わせて決めれば良い。

/etc/nginx/sites-enabled/xxx)
server {
    listen 443 ssl;
    server_name 192.168.x.xx

    ssl_certificate /etc/nginx/ssl/lan.crt;
    ssl_certificate_key /etc/nginx/ssl/lan.key;

    # --- 0. Authelia 自体の設定 ---
    # 混同を避けるため、/authelia/ というパスでログイン画面を動かします
    # "location /"より上に置く必要あり
    location /authelia/ {
        auth_request off; # 明示的に認証チェックoff
        proxy_pass http://127.0.0.1:9091/; # 末尾の / が重要
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # autheliaが内部で使う/api、/staticも認証除外にする
    location /api/ {
        auth_request off;
        proxy_pass http://127.0.0.1:9091/api/;
        proxy_set_header Host $host;
    }

    location /static/ {
        auth_request off;
        proxy_pass http://127.0.0.1:9091/static/;
        proxy_set_header Host $host;
    }

    # --- 1. メインのアプリ(Mjpg-streamer)の設定 ---
    location / {
        # Autheliaに認証を確認しに行く
        auth_request /internal/authelia/authz;

        # 認証成功時、Autheliaからユーザー情報を受け取る
        auth_request_set $user $upstream_http_remote_user;
        proxy_set_header Remote-User $user;

        # エラー(未認証)なら、Autheliaのログイン画面へ飛ばす
        error_page 401 = @error401;

        # 本来のmjpg-streamerへ転送
        proxy_pass http://192.168.x.xx:80xx/;

        # ストリーミングをスムーズにするための設定
        proxy_buffering off;
        proxy_request_buffering off;
        # 接続を維持(Keep-alive)しやすく
        proxy_http_version 1.1;
    }

    # --- 2. 認証チェック用(内部処理用) ---
    location = /internal/authelia/authz {
        internal;
        proxy_pass http://127.0.0.1:9091/api/verify;
        proxy_set_header Host $host;
        proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Content-Length "";
        proxy_pass_request_body off;
    }

    # --- 3. 未認証時にログイン画面へ飛ばす設定 ---
    location @error401 {
        # ログイン後、元のURLに戻れるように引数 (?rd=...) を付ける
        return 302 https://192.168.x.xx/authelia/?rd=$scheme://$http_host$request_uri;
    }
}

設定変更後、以下を実行して設定反映を。

sudo nginx -t
sudo systemctl restart nginx

7.デバイス登録を完了させる手順

7.1 nginxサーバーに接続

https://192.168.x.xx (httpsであることを確認)にアクセス。
警告画面が出たら「詳細設定」からアクセスを許可。
ID/パスワード入力しログインを試みると画面が遷移する。

7.2 登録用QRコードのスキャン

ラズパイのターミナルで cat ~/authelia/config/notification.txt を実行。
登録用URLが表示されるので、PCのブラウザのアドレスバーに貼り付けて開く。
ブラウザにQRコードの画面が表示される。
スマホの認証アプリ(Google Authenticatorなど)でQRコードをスキャン。
(このスキャンでサーバーで生成されたsecretがスマホに保存される)
スマホに表示された6桁の数字(TOTP)をブラウザに入力すると認証される。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?