投稿者: stmtok

  • SSHの設定を再確認

    Ubuntu 22.04でsshサーバの設定 /etc/ssh/sshd_config を行っていたところ,PasswordAuthentication no を設定していたにもかかわらず,パスワード認証が無効になっていなかった.

    原因としては/etc/ssh/sshd_config.d/50-cloud-init.confPasswordAuthentication yesの記述があったため,こちらの設定が優先されていた.

    加えて,ChallengeResponseAuthentication または
    KbdInteractiveAuthenticationyes かつ UsePAMyes の場合,pam設定がデフォルトの場合もパスワードによる認証のみでログインできてしまう.これはpamによる2段階認証などを提供する仕組みである.

    これを機にSSHの設定の見直しを行った.

    sshd_config の先頭に
    Include /etc/ssh/sshd_config.d/*.conf があり,sshd_config.d内の.confをファイル名順に参照し,先勝ちでパラメータが設定されているようである.(システムによっては上書きになるものもあるのでややこしい)

    公開鍵認証

    /etc/ssh/sshd_config.d/00-publkey-auth.conf を作成

    PermitRootLogin no
    PubkeyAuthentication yes
    PasswordAuthentication no

    50-cloud-init.confは必要ないのであれば削除しても良いだろう.

    2段階認証

    パスワード認証 + Google Authenticatorによる認証を行う.公開鍵認証とは別に動作することに注意.

    パッケージのインストール

    # apt install libpam-google-authenticator libqrencode4

    /etc/pam.d/sshdを編集します.

    auth required pam_google_authenticator.so

    /etc/ssh/sshd_config.d/100-google-authenticator.confを作成します.

    KbdInteractiveAuthentication yes
    UsePAM yes

    sshdを再起動します.

    # systemctl restart ssh

    ユーザーの設定 google-authenticatorコマンドを実行

    $ google-authenticator
    Do you want authentication tokens to be time-based (y/n) y
    Your new secret key is: **************************
    Enter code from app (-1 to skip): 

    QRコードを読み取るか,Secret keyを設定してコードを取得します.

    ワンタイムコードを入力するか-1を入力すると以下のように設定項目に関する質問があります.デフォルトで問題ないので全てyを選択します.

    Your emergency scratch codes are:
      ********
      ********
      ********
      ********
      ********
    
    Do you want me to update your "/home/user/.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
    
    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) 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) y

    sftp

    ファイルサーバなどでsftpやscpのみに制限する.

    /etc/ssh/sshd_config.d/50-sftp.conf を作成する

    AllowTcpForwarding no
    x11Forwarding no
    ForceCommand internal-sftp

    ForceCommand internal-sftpを指定することにより,sshすると
    This service allows sftp connections only. とメッセージが表示されconnectionがcloseされる.

  • virsh console接続設定

    virsh console接続設定

    シリアル通信設定

    # vi /etc/default/grub
    
    GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,115200n8"

    GRUBの更新

    Ubuntu

    # update-grub

    CentOS

    # grub2-mkconfig -o /boot/grub2/grub.cfg

    シリアルサービスを有効化

    systemctl enable --now serial-getty@ttyS0

    再起動

    ホスト設定

    # virsh edit <ゲスト>
    
    <device>
      <serial type='pty'>
        <target port='0'/>
      </serial>
      <console type='pty'>
        <target type='serial' port='0'/>
      </console>
    ...

  • TensorFlow.js の備忘録

    TensorFlow.js の備忘録

    EMNISTをPythonで学習した後,TensorFlow.jsでブラウザ上で文字認識を行うところまでの備忘録.

    環境

    • Ubuntu 24.04
    • Python3.8

    Jupyter環境の整備

    jupyterhubをインストールしてサービスを作成します.

    # apt install nodejs npm
    # npm install -g configurable-http-proxy
    # python3 -m venv /usr/local/share/jupyterhub
    # source /usr/local/share/jupyterhub/bin/activate
    (jupyterhub)# pip install jupyter jupyterhub jupyterlab matplotlib numpy

    jupyterhubの設定ファイルを作成します.venvを利用しているので,jupyterhub-singleuserのパスを通すか以下編集します.

    (jupyterhub)# mkdir -p /etc/jupyterhub
    (jupyterhub)# cd /etc/jupyterhub
    (jupyterhub)# jupyterhub --generate-config
    (jupyterhub)# vi /etc/jupyterhub/jupyterhub_config.py
    
    c.Spawner.cmd = ['/usr/local/share/jupyterhub/bin/jupyterhub-singleuser']

    jupyterhubのサービスを作成します.ServiceUserを作成した方が良いでしょう.

    # vi /etc/systemd/system/jupyterhub.service
    
    [Unit]
    Description=JupyterHub
    After=network.target
    
    [Service]
    User=root
    ExecStart=/usr/local/share/jupyterhub/bin/jupyterhub -f /etc/jupyterhub/jupyterhub_config.py
    WorkingDirectory=/var/lib/jupyterhub
    Restart=always
    
    [Install]
    WantedBy=multi-user.target

    jupyterhubのサービスを起動します.

    # mkdir -p /var/lib/jupyterhub
    # systemctl daemon-reload
    # systemctl start jupyterhub

    Python3.8とTensorFlowのインストール

    TensorFlow.jsがPython3.8でないとうまく動かないという情報があったため,Python3.8をインストールして利用する.またjupyterから利用するためにkernelを登録する

    # add-apt-repository ppa:deadsnakes/ppa
    # apt update
    # apt install -y python3.8 python3.8-distutils python3.8-venv
    $ python3.8 -v venv tensorflow
    $ source tensorflow/bin/activate
    (tensorflow)$ pip install tensorflow tensorflowjs matplotlib ipykernel
    (tensorflow)$ python3 -m ipykernel install --user --name tensorflow --display-name "Python 3.8 (TensorFlow)" 

    学習

    kaggleのemnistデータセットをダウンロードします.

    $ #!/bin/bash
    curl -L -o ~/Downloads/archive.zip\
    https://www.kaggle.com/api/v1/datasets/download/crawford/emnist
    $ unzip archive.zip

    適当にモデルを作成,学習します.

    import tensorflow as tf
    import numpy as np
    from tensorflow.keras import layers
    from tensorflow.keras import losses
    import os
    import pandas as pd
    DATA_DIR = "."
    TRAIN_CSV = os.path.join(DATA_DIR, "emnist-letters-train.csv")
    TEST_CSV = os.path.join(DATA_DIR, "emnist-letters-test.csv")
    
    # データの読み込み
    def load_emnist_data(train_csv, test_csv):
        # トレーニングデータの読み込み
        train_df = pd.read_csv(train_csv, header=None)
        test_df = pd.read_csv(test_csv, header=None)
    
        # 特徴量(画像データ)とラベルに分割
        train_images = train_df.iloc[:, 1:].values.astype(np.float32)
        train_labels = train_df.iloc[:, 0].values.astype(np.int32)  # 最初の列がラベル
        test_images = test_df.iloc[:, 1:].values.astype(np.float32)
        test_labels = test_df.iloc[:, 0].values.astype(np.int32)
    
        # ピクセル値を 0-1 に正規化
        train_images /= 255.0
        test_images /= 255.0
    
        # 画像を28x28にリシェイプ
        train_images = train_images.reshape(-1, 28, 28).transpose(0,2,1)
        test_images = test_images.reshape(-1, 28, 28).transpose(0,2,1)
    
        return train_images, train_labels, test_images, test_labels
    
    train_images, train_labels, test_images, test_labels = load_emnist_data(TRAIN_CSV, TEST_CSV)
    
    # モデルの定義
    model = tf.keras.models.Sequential([
        layers.Flatten(input_shape=(28, 28)),
        layers.Dense(128, activation='relu'),
        layers.Dropout(0.2),
        layers.Dense(62)
    ])
    
    # モデルのコンパイル
    model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
                  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                  metrics=['accuracy'])
    # モデルの学習
    model.fit(train_images, train_labels, epochs=10, batch_size=64, validation_split=0.1)
    # モデルの評価
    test_loss, test_accuracy = model.evaluate(test_images, test_labels, verbose=2)
    print(f"Test accuracy: {test_accuracy}")
    # モデルの保存
    model.save('emnist_model.keras')

    変換

    tensorflowjs_convertを利用してkerasモデルをtensorflowjsモデルに変換します.

    $ tensorflowjs_converter --input_format=keras emnist_letters_model.keras tfjs_model

    推論

    変換したモデルを読み込みtensorを投げてレスポンスが帰ってくるところまで確認します.

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width,initial-scale=1.0">
        <title>TFJS</title>
        <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
        <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js"></script>
    </head>
    
    <body>
        <script>
            let canvas = document.createElement("canvas")
            canvas.width = 120
            canvas.height = 120
            let ctx = canvas.getContext("2d")
            console.log(ctx)
            console.log(tf)
            tf.loadLayersModel("/model/model.json").then((model) => {
                console.log(model)
                ctx.fillStyle = "black"
                ctx.fillRect(0, 0, 120, 120)
                let image = ctx.getImageData(0, 0, 120, 120)
                let tensor = tf.browser.fromPixels(image, 3)
                    .toFloat()
                    .resizeBilinear([28, 28])
                    .mean(2, true)
                    .div(tf.scalar(255))
                    .reshape([1, 28, 28])
                let data = model.predict(tensor)
                    .dataSync()
                console.log(tf.argMax(data).arraySync())
            })
        </script>
    </body>
    
    </html>

    動作確認だけ.

  • UbuntuでActive Directory ドメインに参加する

    UbuntuでActive Directory ドメインに参加する

    ローカルネットワーク内にActive Directory Domain Serviceが稼働している前提.

    ドメイン環境

    • ドメイン名:stmtok.com
    • ホスト名 :ad.stmtok.com
    • NetBIOS名 :AD
    • レルム  :STMTOK.COM

    パッケージのインストール

    # apt -y install realmd sssd sssd-tools libnss-sss libpam-sss adcli samba-common-bin packagekit

    DNSの変更

    # vi /etc/netplan/01-confg.yaml
    
    network:
      ethernets:
        enp1s0:
          dhcp4: true
          nameservers:
            addresses: [192.168.1.200]
            search: [stmtok.com]
    
    # netplan apply

    Active Directory ドメインを discover する

    # realm discover STMTOK.COM
    stmtok.com
      type: kerberos
      realm-name: STMTOK.COM
      domain-name: stmtok.com
      configured: no
      server-software: active-directory
      client-software: sssd
      required-package: sssd-tools
      required-package: sssd
      required-package: libnss-sss
      required-package: libpam-sss
      required-package: adcli
      required-package: samba-common-bin

    Active Directory ドメインに join する

    # realm join STMTOK.COM
    Password for Administrator:

    確認

    # id user@stmtok.com
    uid=1905401104(user@stmtok.com) gid=1905400513(domain users@stmtok.com) groups=1905400513(domain users@stmtok.com)

    ユーザ名を省略する

    # vi /etc/sssd/sssd.conf
    
    use_fully_qualified_names = False
    
    # systemctl restart sssd
    # id user
    uid=1905401104(user) gid=1905400513(domain users) groups=1905400513(domain users)

    UNIX属性のUID/GIDを利用する

    # vi /etc/sssd/sssd.conf
    
    ldap_id_mapping = False
    ldap_user_uid_number = uidNumber
    ldap_user_gid_number = gidNumber
    
    # systemctl restart sssd
    # sss_cache -u user
    # id user
    uid=2000(user) gid=2000(users) groups=2000(users),1905400513(domain users)

    以上.

  • Raspberry Pi でWordPressを動かす

    Raspberry Pi でWordPressを動かす

    備忘録を残すために,すでに運用していたRaspberryPi上にWordPressを構築します.環境は以下の通り.

    • Raspberry Pi 3 Model B+
    • apache2 + php
    • mariadb-server

    パッケージのインストール

    必要なパッケージをインストールします.

    # apt install -y apache2 php mariadb-server

    データベースの作成

    WordPressで利用するデータベースとユーザを作成します.

    # mysql
    MariaDB [(none)]> create user 'wp'@'localhost' identified by 'password';
    MariaDB [(none)]> create database wordpress;
    MariaDB [(none)]> grant all privileges on wordpress.* to 'wp'@'localhost';

    WordPressのダウンロード

    WordPressの最新版をダウンロードします.

    $ wget wget https://ja.wordpress.org/latest-ja.tar.gz

    展開して配置します.

    $ tar zxf latest-ja.tar.gz
    # mv wordpress /var/www/wordpress
    # chown -R www-data:www-data /var/www/wordpress

    設定ファイルを編集します.

    # mv /var/www/wordpress/wp-config-sample.php /var/www/wordpress/wp-config.php
    # vi /var/www/wordpress/wp-config.php
    
    define( 'DB_NAME', 'wordpress' );
    define( 'DB_USER', 'wp' );
    define( 'DB_PASSWORD', 'password' );
    define( 'DB_HOST', 'localhost' );
    
    define( 'AUTH_KEY',         '乱数' );
    define( 'SECURE_AUTH_KEY',  '乱数' );
    define( 'LOGGED_IN_KEY',    '乱数' );
    define( 'NONCE_KEY',        '乱数' );
    define( 'AUTH_SALT',        '乱数' );
    define( 'SECURE_AUTH_SALT', '乱数' );
    define( 'LOGGED_IN_SALT',   '乱数' );
    define( 'NONCE_SALT',       '乱数' );

    Apacheの設定

    phpを有効にします.

    # a2enconf php7.4-fpm 

    rewriteを有効にします.

    # a2enmod rewrite

    DocumentRootを変更します.

    # vi /etc/apache2/sites-enabled/000-default.conf
    
    DocumentRoot /var/www/wordpress

    Apacheを再起動します.

    # systemctl restart apache2

    WordPressの初期設定

    Webブラウザからアクセスして初期設定すれば完了.リバースプロキシ下でhttpsアクセスの場合はwp-config.phpに以下の設定を忘れずに.

    if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
        $_SERVER['HTTPS'] = 'on';
    }
  • 姫路城を見学

    11月某日に姫路に行く用事があり,姫路城にも行ってきました.のんびり周っていたら閉園ギリギリになってしまいましたが,おかげで夕焼けに照らされるかっこいいお城を見ることができました.