Ubuntuのメジャーアップデート

自宅NASのOSアップデートをやろうやろうと思いつつ、気付けば20.04 LTSの通常サポート終了から半年も経っていました。
ESMでセキュリティパッチを当てているとはいえ、通常サポート有効な24.04 LTSへアップデートしていきます。

# まずはパッケージの更新
apt update
apt dist-upgrade

# アップデートチェック
# Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. と怒られたときは
# /etc/update-manager/meta-release 内のhttps:// を http:// に変更
do-release-upgrade -c
Checking for a new Ubuntu release
New release '22.04.5 LTS' available.
Run 'do-release-upgrade' to upgrade to it.

# 2つ一気にアップデートできないので、まずは22.04に
do-release-upgrade

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts.
Check your Internet connection or proxy settings
# 上のエラーが出た場合は、/etc/update-manager/meta-release 内の https:// を http:// に編集して再試行

# SSH経由ではContinue running under SSH? が出る。
# ローカル接続も可能にしておき、Yで続行
# しばらく待つと  Continue [yN]  Details [d] が出るので、dで詳細を確認しておく
# qで抜け、Yで続行
# Configuring libc6 は関連サービスを更新中に自動で再起動するかの確認なので、Yesで続行
# Samba server and utilities や Configuring openssh-server は設定保持のため keep the local version currently installed で続行
# XX packages are going to be removed. Continue [yN]  Details [d] は一応dで見ておく
# Restart required までいけばひと段落

これで1段落、22.04になったので、再度同じ手順で24.04まで上げます。
なお、アップデート後は以下対応が必要でした。

1. SSH接続(公開鍵)不可 (20.04 → 22.04)

アップデート後再起動し、再度SSH接続を試行したところ繋がらず…
ローカルでsshd_configを編集しパスワード認証を一時的にONにしてリカバリの上、 /var/log/auth.log を眺めたところいかにも怪しい以下ログを発見しました

userauth_pubkey: key type ssh-rsa not in PubkeyAcceptedAlgorithms [preauth]

どうやらssh-rsaが許可されたアルゴリズムに含まれていない様子。
そもそも認証用のキーペアを作ったのが数年前で、当時のTeraTermはSHA1のみに対応していたようです。SHA1は既に脆弱性が指摘されており非推奨なので、これを機にED25519のキーペアに変更しました。変更後は公開鍵認証もできるようになったので、一時許可していたパスワード認証を不許可に戻して対処終了。

2. pip使用不可 (22.04 → 24.04)

luksで各ボリュームを暗号化しているため、ユーティリティをPythonで自作し運用しています。アップデート後はライブラリを入れなおす必要ありでした。
おまけに24.04ではpipが使えないようで…
PyCryptodome を apt install python3-pycryptodome で入れたは良いものの、ModuleNotFoundError: No module named ‘Crypto’ で暫し時間を溶かしました。
結局 import の Crypto を Cryptodome に変えて解消。

3. clevisのtpmバインド不可 (22.04 → 24.04)

clevis encrypt tpm2 と打ったらコマンドが違うと怒られる始末。
clevis-tpm2 が消えてしまったようなので再インストールします。
apt install clevis-tpm2 にて解消。

4. Zpoolのupgrade要求

一通りアップデートした後、zpool status を見てみたらupgrade要求の表示が。
害はなさそうなのでupgradeを行いました。

zpool status
  pool: tank
 state: ONLINE
status: Some supported and requested features are not enabled on the pool.
        The pool can still be used, but some features are unavailable.
action: Enable all features using 'zpool upgrade'. Once this is done,
        the pool may no longer be accessible by software that does not support
        the features. See zpool-features(7) for details.

zpool upgrade -v # これで詳細情報確認可能
zpool upgrade -a # 害なさそうなので全てアップグレード

幸い互換性面で大きな影響は出ず、無事アップデートが完了です


参考
Ubuntu 18.04(LTS)→20.04(LTS)アップグレード方法
Ubuntu 18.04 LTSのサポート終了が終了するので20.04へアップグレードする
Ubuntu 18.04から20.04へのアップグレード時に「Failed to connect to https://changelogs.ubuntu.com/meta-release-lts.」
【RHEL9】Teratermで作ったRSA鍵が公開鍵認証で使えない

サブNASの整備 (1) – ProDesk 600 G4 の電源・ケース換装

自宅のNASはZFSによるHDDレベルの冗長構成はとっているものの、NAS自体は1台のみのため自宅被災等で損害を被る可能性があります。今回はサブNASを整備し実家に設置することで、クラウドサービスでいうところのマルチリージョン構成を実現し、さらなる耐障害性の向上を図ります。

1. ハードウェア選定と調査

HDD以外の通常PCと構成が同一な部分は、以前どこかの安売り時に購入していたリース落ちのHP ProDesk 600 G4 SF を利用することにしました。第8世代のCore i5 にメモリが8GB、SATAもオンボードで3ポートとなかなか使える構成です。
ここにSATAを2ポート拡張カードで追加すれば、HDD5本のRAID-Z1構成をNAS用のデータ領域として使用できます。
一方課題は電源とケースですね。ケースは当然3.5inchを5つも格納できるような余裕はないので交換必須、電源もデフォルトだと180Wと小さいので交換することにしました。

ところがこの電源が曲者で… PSUからは3種類のコネクタが出ており、内2つはATX電源でCPU用としてよく使われるATX12V 4ピンコネクタ、のこりはストレートの制御用らしき7ピンコネクタ(ただし線は5線、2ピン未使用。サイズはJSTのPHコネクタと同じ) と単純にATX電源と交換は難しいようです。

図1 電源コネクタの配置

先達の見識をお借りし、出力の実測も行って以下のことがわかりました。

<P1, 3のコネクタについて>

  • ピンアサインはATX12V 4ピンコネクタと同一で、出力電圧も12V
  • PSUのACインレット接続時点で12Vが出力される (スタンバイ電源扱いの様子)

<P2のコネクタについて>

  • 3, 7ピン(黒) はGND
  • P2の4ピン(緑) はACインレット接続時点で+3.3Vにプルアップ。GNDに落とすとPSUのファンが回る (ATX電源のPS_ONと同様の動作?)
  • P2の5ピン(灰)は12V版のPower good。ここを外すと電源エラーで起動しない。MB側に結線しないと+12V(11.62Vほど)を出力しているが、MBに結線すると0V付近まで落ちる。
    ATX電源の+12V出力から、100kΩの抵抗を介して結線したところ電源エラー無く起動に成功
  • P2の6ピン(紫) は不明。このピンのみを外しても正常に起動することから、ATX電源化にあたっては考慮しない(未結線)ものとする
    (参考:通常起動後は0V付近で安定している。少なくともATX電源で同じ線色が割り当てられている+5V Standby ではなさそう)

2. 電源コントロール回路の設計と作製

前項で調査した仕様から、ATX電源を常にON状態にしてP2 5ピンに12Vをかけておけば動作する見込みは立ちました。
とはいえ常時ONは気持ち悪いので、電源SWとP2 4ピンを入力、ATX電源側のPS_ONとMB上の電源SW端子を出力として、マイコンを使用した電源コントロール回路を設計します。実現したい入出力の遷移は以下のようなものになります。
(注:出力はどちらもマイコンから見たレベルで、PSU / MB 側とは反転)

図2 入出力遷移
  • PSUがOFFの状態で電源SW押下時、即時でPS_ONをGNDに落とす。12V供給が安定した後、MB側の電源SW押下を模倣する (起動動作)
  • PSUがONの状態でP2 4ピンの立ち上がり(=MB側の電源OFF) 時、一定時間をおいてP2がHのままであればPS_ONをHにしてPSUの電源を落とす (停止動作)
  • PSUがONの状態で電源SW押下時、MB側の電源SW押下を模倣する (電源SW通過動作)

以上の動作を実現させる回路とプログラムは以下の通りです。

図3 回路図
bool fl = false;  //通常電源ON動作フラグ
bool fl2 = false; //PSU電源OFFフラグ 

ISR(PORTA_PORT_vect){
  uint8_t intflags = PORTA.INTFLAGS;
  if(!fl && !fl2){
    if(bit_is_set(intflags, 2)){        //PWR_SW_IN 割込
      if(bit_is_set(PORTA.IN, 2)){      //L → Hの場合
        if(bit_is_set(PORTA.IN, 6)){    //MB_STR_INがH
          fl = true;  //通常電源ON動作実施
        } else {
          PORTA.OUT |= 0b10000000;  //MB_SW_OUTをHに
        }
      } else {                          //H → Lの場合
        PORTA.OUT &= 0b01111111;  //MB_SW_OUTをLに
      }
    } else if(bit_is_set(intflags, 6)){ //MB_STA_IN 割込
      fl2 = true; //PSU電源OFF動作実施
    }
  }
  PORTA.INTFLAGS = PORT_INT2_bm | PORT_INT6_bm ;  //割り込み要求フラグ解除
}

void setup() {
  PORTA.DIR = 0b10001010; //入出力設定
  PORTA.OUT = 0b00000000; //全LOW
  PORTA.PIN2CTRL |= 0b00000001;  //PA2は両端割り込み
  PORTA.PIN6CTRL |= 0b00000010;  //PA6は立上割り込み
  sei();  //割り込み許可
}

void loop() {
  if(fl){
    PORTA.OUT |= 0b00000010;  //PSU_CTR_OUTをHに
    delay(6000);
    PORTA.OUT |= 0b10000000;  //MB_SW_OUTをHに
    delay(1000);
    PORTA.OUT &= 0b01111111;  //MB_SW_OUTをLに
    fl = false; //動作終了
  }
  if(fl2){
    delay(10000);
    if(bit_is_set(PORTA.IN, 6)){    //MB_STR_INがH
      PORTA.OUT &= 0b11111101;  //PSU_CTR_OUTをLに
    }
    fl2 = false;
  }
  delay(10);
}

3. ケースの換装

電源がどうにかなったので、あとはケースです。MBのサイズやねじ穴位置は独自なので、サイズ的に問題がなかったMicroATX対応ケースにスペーサーを穴あけして取り付けて固定します。3Dプリンタで製作したマウンタも併用しました。

図4 ケースへの取り付け

なお、DisplayPortの片方や音声出力を潰しているのは下のスペースにHDDを置くためです。昨今の(というか昔でも)MicroATXケースに3.5inchベイは5つもないので、当然3Dプリンタで自作します。

図5 HDDマウンタ設置後

これでどうにか、ハードウェア面の準備は整いました。


参考
hp prodesk 400 G5 SFF 通常電源に
hp prodesk 400 G5 SFF ケース交換

Windows 11のクリーンイストール

Windows 10 のEOSを今年の10月に控え、いよいよ重い腰を上げてWindows 11 へのアップデートをすることにしました。
Cドライブ容量も500GBでは足りなくなってきましたので、倍の1TBに換装しつつクリーンインストールします。ただし昨今のMicrosoftのアカウント紐づけ圧力が鬱陶しいので、あくまでもローカルアカウントでのサインインを堅守する形で移行します。

1. 下準備

何はともあれSSDの換装です。
現行はCドライブ500GB + 速度の要るデータの置き場や一時領域として2TB の2SSD構成ですが、インストール時に過って現行ドライブを上書きしないよう、両方取り外して新規のSSDのみを接続しました。

あとはMicrosoftの公式から最新のmediacreationtool.exe を落とし、適当なUSBメモリをインストールメディアにしておきます。

2. Windows11のインストール

先ほど作ったUSBからブートし、まずは通常通りインストールを進めます。

ライセンスはMicrosoftアカウントに紐づいている旧Windows 10 のものをそのまま使うため、プロダクトキー入力はスキップします。

これで「インストール」ボタンを押せば開始されます。再起動しつつ少しかかりますので、お茶でも飲んでいましょう。
下の画面になったら作業を再開します。

この画面で、ローカルアカウントでセットアップするための準備が必要です。
Shift + F10 でコマンドプロンプトを起動し、以下を入力します。

cd oobe
BypassNRO.cmd

これで再起動され、準備完了です。先に進むと「インターネットに接続されていません」が選択できるようになっているので、こちらを押下すればローカルアカウントでセットアップが可能です。

ちなみに、Windows7/8から10/11への無償アップグレードが2023/9/20に終了したという情報があったのでライセンス認証が通るか心配でしたが、Win10のライセンスをMicrosoftアカウントに紐づけていたおかげか問題なく認証できました。
試していませんが、大本の8.1のプロダクトキーを入れると弾かれるのでしょうね。
自作勢は構成変更などで認証が外れることもあるので、いくらMicrosoftアカウントを毛嫌いしていてもライセンスは紐づけておかねばと改めて心に留めました。

3. 設定変更

インストールが終われば、あとは初期設定です。
不要なプリインストールアプリを削除し、項目が減らされた右クリックメニューを元に戻し、不要なおすすめ機能を無効化し、エクスプローラをサードパーティアプリでWin10同様のものに戻します。
昔ながらの人間だと新しいUIに慣れなくてなんとも… です。
これで作業はひと段落。幸い後方互換性はしっかりしていて、使えなくなったソフトウェアはありませんでした。


参考文献
Windowsの調子が……最終手段のクリーンインストールで覚えておきたいテクニック。ローカルアカウントの作り方も紹介

PC起動時にNAS接続できない事象の対処

自宅PCのユーザーフォルダ各種(デスクトップなど)はNASに置いています。
ネットワーク周りをいじった後でPCを再起動したところ、「ネットワーク接続の復元」ダイアログが表示されNASへのアクセスができない事象が発生しました。備忘録として対処法を書き残しておきます。

事象

・起動後ログインすると、以下のダイアログが表示される。

ネットワーク接続の復元
[ドライブ文字] を次に接続しようとしてエラーが発生しました
\\hoge\fuga
Microsoft Windows Network: ローカル デバイス名は既に使用されています。

この接続は復元されませんでした

・[OK] を押下して数秒待てばNASに接続されるものの、毎度上記ダイアログが表示される状態。

対処法

・ネットワーク設定を、パブリックネットワークからプライベートネットワークへ変更する

今回は意図的に変えていないのですが、ネットワーク周り(WAN側)の変更を起因としてか自動的にプライベート → パブリック の変更がされていたようでした。

LTOドライブの導入

手元で管理しているデータ量が多くなり、ある程度はコールドストレージへ移動すべきだろうと思い立ちました。
丁度LTOドライブも生えてきたので() 、使えるようにしていこうと思います。

1. 用意するもの

  • LTOドライブ (今回はLTO6に対応したBRSLA-1204-DCを使用)
  • ドライブに合ったインターフェースカード (SASのためLSI社の SAS 9212-4i4eを使用)
  • SFF-8482 to SATA 変換ケーブル
  • 適当なコンピュータ (Ubuntu 20.04.6 LTS インストール機を使用)

2. SASカードの準備

まずは、SAS 9212-4i4e のドライバインストール要否を確認します。

lshw -C storage
  *-sas
       description: Serial Attached SCSI controller
       product: SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon]
       vendor: Broadcom / LSI
       physical id: 0
       bus info: pci@0000:01:00.0
       version: 03
       width: 64 bits
       clock: 33MHz
       capabilities: sas pm pciexpress vpd msi msix bus_master cap_list rom
       configuration: driver=mpt3sas latency=0
       resources: irq:16 ioport:e000(size=256) memory:f7cc0000-f7cc3fff memory:f7c80000-f7cbffff memory:f7c00000-f7c7ffff

きちんと認識されており、driver として mpt3sas が使われているようです。
手当て不要であっさり終わりました。

3. LTOドライブの接続と状態確認

ではいよいよ、LTOドライブを繋いでみます。
テープドライブは/dev/st* で認識されますが、残念ながらただ繋いだだけでは認識してくれませんでした。
stドライバは追加ドライバパッケージである linux-modules-extra に含まれているようですので、インストールします。

apt search linux-modules-extra-`uname -r`
linux-modules-extra-5.15.0-91-generic/focal-updates,focal-security 5.15.0-91.101~20.04.1 amd64
  Linux kernel extra modules for version 5.15.0 on 64 bit x86 SMP

apt install linux-modules-extra-`uname -r`

再起動すると、無事に認識されました。
続いて、状態確認ツール(HPE Library and Tape Tools)をインストールしていきます。公式からtarを落とし、サーバへ移しておきましょう。
rpmのみ提供の、RHEL系前提のツールのため alien を使用してインストールします。

tar -xvf ./hpe_ltt64_linux_x86_64.tar
alien ./hpeltt-6.5.0.10-4.x86_64.rpm    #rpmの変換
dpkg -i hpeltt_6.5.0.10-5_amd64.deb     #インストール
apt install libncurses5                 #依存パッケージのインストール
/opt/ltt/hpe_ltt                        #インストールしたツールの実行

癖のあるUIですが、初回起動時にドライブ状態を調べるには次のような操作を行います。

  1. Press any key to continue
    任意のキーを押して続行します
  2. Scan Mode Selection
    1 [X] Hardware Scan が選択されていることを確認の上、”continue”と入力してエンターを押下します
  3. Main
    Processors/Enclosures: 以下 Drives: にLTOドライブが認識されていることを確認の上、”select 1″と入力してエンターを押下します (1 はLTOのドライブ番号)
  4. Main > Drive Information
    少し待つとこの画面になり、ドライブの情報(と、テープを入れていればテープの情報)が表示されます。”health”と入力してエンターを押下します
  5. Main > Drive Information > Support Ticket
    “extract”と入力してエンターを押下します
    プロンプトが帰ってきたら、”view”で閲覧、”save”で保存ができます

なお、閲覧時のページ送りは Ctrl-D / Ctrl-U で実施できます。
また、入力コマンドに困った場合は何も入力せずEnterを押下すれば、コマンド一覧が表示されます。
ちなみに、save するとサポートチケット形式(.lzt)で保存されますが、次のようにしてxmlへ変換できます。

/opt/ltt/hpe_ltt -f xmlticket file=<original.lzt> filename=<converted.xml>

4. 暗号化のサポート

LTO-4以降では暗号化が使えますので、ツールを入れておきます。
stenc と呼ばれるソフトウェアで、READMEの通りにインストールします。

apt install pkg-config pandoc                                 #必要なパッケージ群の事前インストール
git clone https://github.com/scsitape/stenc.git
cd stenc/
autoreconf --install
./autogen.sh && ./configure  
make check
make
make install
stenc -f /dev/nst0                         #情報の表示
Status for /dev/nst0 (HP Ultrium 6-SCSI 32DW)
--------------------------------------------------
Reading:                         Not decrypting
Writing:                         Not encrypting
Key instance counter:            0
Supported algorithms:
1    AES-256-GCM-128
     Key descriptors allowed, maximum 32 bytes
     Raw decryption mode allowed, raw read disabled by default

5. LTFSのサポート

LTO-5以降では、通常ストレージのように使用できるLTFS (Linear Tape File System) に対応しています。
これをサポートするソフトウェア (HPE StoreOpen and LTFS Software) を導入します。
HPE Library and Tape Tools の時と同様、公式からtarを落としておきましょう。

tar -xvf ./HPE_StoreOpen_Software_3.5.0_RHELx64.tar.gz
alien ./HPE-SOS-3.5.0-62.x86_64.rpm     #rpmの変換
dpkg -i hpe-sos_3.5.0-63_amd64.deb      #インストール

#--- libicui18n.so.50 がないと怒られるので、ソースからビルドする ---#
wget https://github.com/unicode-org/icu/releases/download/release-50-2/icu4c-50_2-src.tgz
tar -xvf ./icu4c-50_2-src.tgz
cd icu/source
./runConfigureICU Linux
make
make install                           #デフォルトでは /usr/local/lib/ にインストールされる
echo "/usr/local/lib/" | tee -a /etc/ld.so.conf.d/HPE-SOS.conf
ldconfig -v

mkltfs –help と打って、ヘルプが出れば問題なくインストールできています。

6. テープへの書き込み (暗号化あり)

これで準備が整ったので、いよいよ書き込みを行います。
まずは、暗号化鍵を生成し、ドライブにロードします。

openssl rand -out keyfile.key -hex 32          #鍵生成
echo "description" >> keyfile.key              #鍵説明の追加 (オプション)
stenc -f /dev/nst0 -e on -d on -k keyfile.key  #キーのロード (ドライブのEncryption LED が青く光る)

続いて、LTFSでフォーマット (この表現が正しいか怪しいですが)し、マウントします。

mkltfs -d /dev/nst0
ltfs /mnt/lto
df -h
Filesystem             Size  Used Avail Use% Mounted on
  (略)
ltfs:/dev/nst0         2.3T     0  2.3T   0% /mnt/lto

あとは、通常のドライブのように使うだけです。
取り出しは、通常通りumountしてイジェクトします。暗号化キーのアンロードは忘れないようにしましょう。

umount /mnt/lto
ps aux | grep ltfs                                              #マウントポイントが表示されないことを確認する
root 15887 0.0 0.0 451956 4088 ? Ssl 11:05 0:00 ltfs /mnt/lto/  #こういうレコードがあれば、まだ終了処理中
stenc -f /dev/nst0 -e off -d off                                #暗号化キーのアンロード
stenc -f /dev/nst0                                              #アンロードの確認

参考
Where can I find the /dev/st tape drivers on Ubuntu?
UbuntuのLinuxカーネルアップグレード
中古で入手した LTO ドライブの状態を調べる方法
HPE Library & Tape Toolsをubuntu 22.04にインストールする
LTO-5 の暗号化を試す (Ubuntu 22.04, stenc)
Ubuntu 18.04 で LTO-6 の LTFS を使う

RHEL – Ubuntu マルチブート環境の構築

既にRHELが稼働している検証機に、故あってUbuntuを追加しマルチブート環境を構築する必要に迫られました。パーティション操作やGRUBの再設定が必要でやや手間取りましたので、備忘を兼ねて書き残すことにします。

1. 初期状態の確認と方針の策定

検証用RHEL 8.7 環境を確認すると、パーティションとLVMは次のような構造になっていました。

lsblk
  NAME          MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
  sda             8:0    0 465.8G  0 disk
  ├ sda1          8:1    0     1G  0 part /boot
  └ sda2          8:2    0 464.8G  0 part
    ├ rhel-root 253:0    0    70G  0 lvm  /
    ├ rhel-swap 253:1    0   7.8G  0 lvm  [SWAP]
    └ rhel-home 253:2    0   387G  0 lvm  /home

/home は387GBもいらないので、ここを縮小してUbuntu関係のインストール領域に変えることとします。
とはいえ既存のPVにインストールはできないので、/homeの縮小に合わせて大本の物理ディスクパーティションも縮小しましょう。

2. 空き領域の確保

ファイルシステム縮小 → LVM LV縮小 → LVM PV縮小 → パーティション縮小 の順で実施し、空き領域を確保します。
RHELのファイルシステムはXFSですが、ext4と違って単純な縮小に対応しておらず、バックアップ – リストア による手順を採る必要があります。

xfsdump -l 0 - /dev/mapper/rhel-home > /hoge/back.dump #バックアップ取得
umount -l /home                                        #縮小のためアンマウント
lvreduce -L 100G /dev/rhel/home                        #LV縮小
mkfs.xfs -f /dev/mapper/rhel-home                      #縮小後LVに、新規でファイルシステム構築
mount /dev/rhel/home /home                             #リストアのためマウント
xfsrestore -f /hoge/back.dump /home                    #リストア

これで領域が空いたのでpvreduceを、と思いましたが、cannot resizeと怒られました。よく調べてみると、どうやら真ん中の領域が減っただけのようです。

pvdisplay -v -m
  --- Physical volume ---
  PV Name               /dev/sda2
  VG Name               rhel
  PV Size               464.76 GiB / not usable 3.00 MiB
  Allocatable           yes
  PE Size               4.00 MiB
  Total PE              118978
  Free PE               73455
  Allocated PE          45523

  --- Physical Segments ---
  Physical extent 0 to 2002:
    Logical volume      /dev/rhel/swap
    Logical extents     0 to 2002
  Physical extent 2003 to 27602:
    Logical volume      /dev/rhel/home
    Logical extents     0 to 25599
  Physical extent 27603 to 101057:
    FREE
  Physical extent 101058 to 118977:
    Logical volume      /dev/rhel/root
    Logical extents     0 to 17919

それでもLVMであれば pvmove コマンドで Physical extentを移動できるようなので、移動して進めます。pvmoveは時間がかかるので気長に待ちましょう。

pvmove --alloc anywhere /dev/sda2:101058-118977 /dev/sda2:27603-45522  #Physical extent移動
pvresize --setphysicalvolumesize 182096M /dev/sda2                     #PV縮小 (サイズは-tで何度か試行し、ぴったりに合わせる)
pvdisplay --units b                                                    #パーティション分割用に情報取得
  --- Physical volume ---
  PV Name               /dev/sda2
  VG Name               rhel
  PV Size               190940446720 B  / not usable 3145728 B           #必要セクタ数:190940446720 / 512 = 372930560
  Allocatable           yes (but full)
  PE Size               4194304 B
  Total PE              45523
  Free PE               0
  Allocated PE          45523
parted /dev/sda
(parted) unit s
(parted) print
ディスク /dev/sda: 976773168s
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: msdos
ディスクフラグ:

番号  開始      終了        サイズ      タイプ   ファイルシステム  フラグ
 1    2048s     2099199s    2097152s    primary  xfs               boot
 2    2099200s  976773119s  974673920s  primary                    lvm  #ここを、終了:(2099200 + 372930560 - 1) =  375029759 へ変更

(parted) resizepart 2 375029759
警告: パーティションを縮小するとデータを失うかもしれませんが、それでも実行しますか?
はい(Y)/Yes/いいえ(N)/No? Y
(parted) quit

3. Ubuntuのインストール

通常通りインストール用USBからブートし、基本はデフォルト設定で進めていきます。
ただし落とし穴が一つ、なぜかRHELインストール時にMBRディスクとなっていたようで、GPTと思い込みUEFI の表示がある起動デバイスを選択してはboot diskが選択できず小一時間足踏みをしてしまいました。
GPT : UEFI表記有りのインストールメディアからブート
MBR : UEFI表記なしのインストールメディアからブート
するようにしましょう。

あとはCustom storage layout から、2で作った空き領域を/に割り当て、boot diskも選択して待つだけです。
最後のReboot Now で再起動すると、無事Ubuntuが立ち上がりました。

4. RHELブート失敗のリカバリ

Ubuntuインストール後にRHELを起動したところ、以下のような表示が出てブートシーケンスが止まり、レスキューモードに入ってしまいました。

[FAILED] Failed to start Switch Root.
See 'systemctl status initrd-switch-root.service' for details.

Generating "/run/initramfs/rdsosreport.txt"

Entering emergency mode. Exit the shell to continue.
Type "journalctl" to view system logs.
You might want to save "/run/initramfs/rdsosreport.txt" to a USB stick or /boot
after mounting them and attach it to a bug report.

:/#

色々と確認したところ、/sysroot を / にスイッチしようとして失敗したようです。
現状の/sysroot を ls すると、本来あるべき / ではなく /home の内容が表示されました。
LVMを弄ったせいで、/sysroot にマウントされるLVが変わってしまったと推察されます。
まずは起動させないと何もできないので、/sysroot に正しいLVをマウントしてブートシーケンスを続行させます。

:/# umount /sysout
:/# mount /dev/rhel/root /sysroot
:/# exit

無事に起動することが確認できました。
あとは根本的な解決法の模索です。GRUB画面でeを押下し編集画面を確認したところ、ルートデバイスの指定が /dev/dm-* 形式になっていました。Ubuntuインストールによりdm番号がずれ、本来の root ではなく home のLVをルートデバイス扱いにしてしまっているようです。
GRUBの再設定を行います。
(注:バックアップは取りましょう。また、以下の手順はBIOSベースの場合です。UEFIベースの場合は別手順となりますので、参考文献「GRUB2の再インストール」を参照してください)

rm /etc/grub.d/*
rm /etc/sysconfig/grub                    #現状のGRUB設定削除
yum reinstall grub2-tools                 #GRUB再設定
grub2-mkconfig -o /boot/grub2/grub.cfg    #grub.cfg ファイルの再構築

これで、RHEL側のルートデバイスも /dev/mapper/ 形式の指定に更新されました。
Ubuntu, RHELともに正常起動を確認し、作業完了です。


参考文献
rootのXFSファイルシステムを縮小する方法
LinuxのLVMパーティションを縮小してWindowsをインストールした
GRUB 2 の再インストール

BitLocker適用下のWOL (2) – ロック解除機構を読み解く

ロック解除フロー

ネットワークロック解除機能のエミュレートに先立ち、まずはメッセージフローを理解するところから始めます。一通りのロック解除の流れは、以下のようになります。
なお、文中の用語は下部にまとめておきます。

  1. クライアントは、以下の情報を含むNKPU要求パケットをブロードキャストします。
    ・キープロテクター(KP)
    ・KPの暗号化に使用したX.509証明書の拇印
  2. サーバは、当該要求を処理してよいか、以下の観点で確認します。
    ・(オプション)クライアントIPが、許可IPリストに掲載されているものと一致するか
    ・要求で使用された公開鍵に対応する秘密鍵にアクセス可能か(証明書の拇印を用いる)
  3. サーバは、解除要求を許可する場合、以下のようにNKPU応答パケットを生成し、クライアント向けにユニキャストします。
    ・保有する秘密鍵を用いて、KPを復号する
    ・KPに含まれるクライアント鍵(CK), セッション鍵(SK)を用いてキープロテクターレスポンス(KPR)を生成する
    ・DHCPパケットのオプションにKPRを含める

フローを図示すると、以下のようになります。(公式ドキュメントより引用)

出典:[MS-NKPU]: Network Key Protector Unlock Protocol 1.3.1 Message Flow Figure 1: Network key protector unlock process
用語集
  • ・キープロテクター (KP) : CK並びにSKを、X.509公開鍵(PK)にてPKCS#1 v1.5を用いて暗号化したもの。復号すると64 bytesのデータとなり、前半の32 bytesがCK, 後半の32bytesがSKである。
  • ・クライアント鍵 (CK) : クライアントがKPを用いてサーバに送り、サーバからKPRにて返送されることを期待している鍵。サイズは32 bytes
  • ・セッション鍵 (SK) : KPR生成時に使用する、ランダムに生成された32 bytesの鍵。
  • ・キープロテクターレスポンス (KPR) : CKヘッダ(12 bytes固定値, 0x2C 00 00 00 01 00 00 00 06 20 00 00)並びにCKを、SKにてAES-CCMを用いて暗号化し、得られたMAC(16 bytes)と暗号化データをこの順で並べたもの

パケット仕様

では本題の、NKPUで使用されるパケットの仕様を確認していきます。
仕様書上はIPv6, IPv4双方の定義が掲載されていますが、IPv4のみを紹介・実装することにします。

パケット仕様 (1) ― 共通事項

NKPUパケットは、要求/応答共に RFC2131 で規定されるDHCPパケット仕様に準拠します。NKPUに必要な情報は、すべてオプション領域に格納されます。
以下にDHCPパケット並びにそのオプション部のデータ構造を示します。表には参考まで、NKPU応答時に各フィールドにセットする値を記載しますが、独自研究であることに留意してください。

図1 DHCPパケット構造
フィールド名サイズ [byte]説明応答時の値
op1opコード0x02
htype1ハードウェアアドレス種別0x01
hlen1ハードウェアアドレス長0x06
hops1ホップ数0x00
xid4トランザクションID要求時と同一
secs2経過秒数0x00 00
flags2フラグ0x00 00
ciaddr4クライアントIPアドレス0x00 00 00 00
yiaddr4“あなたの”IPアドレス要求時と同一
siaddr4起動処理に使用されるIPアドレス要求時と同一
giaddr4リレーエージェントのIPアドレス要求時と同一
chaddr16クライアントのHWアドレス要求時と同一
sname64サーバーホスト名要求時と同一
file128ブートファイル名要求時と同一
optionvariableオプションパラメータ別途詳細解説
表1 DHCPパケットの各フィールド説明

図2 DHCPオプション領域構造
フィールド名サイズ [byte]説明
Magic Cookie4オプション部の開始を表す0x63 82 53 63
Option Code1オプションコード可変
Option Len1Option Data の長さ可変
Option Datavariableオプションデータ本体可変
End Code1オプション部の終了を表す0xFF
表2 DHCPオプション領域の各フィールド説明

なお、NKPUで使用されるDHCPオプションは、以下の通りです。

Option Code要求時応答時含まれる情報
43 (0x2B)NKPUデータ
60 (0x3C)固定文字列(ASCII) “BITLOCKER”
125 (0x7D)NKPUデータ
表3 NKPUで使用されるDHCPオプション

パケット仕様 (2) ― NKPU要求時のオプション

(2) ― 1 オプション43仕様

本オプションの第1サブオプションには使用される証明書のフィンガープリントが、第2サブオプションにはキープロテクター(KP)の前半部分が含まれます。データ構造並びに各値(独自研究)は以下のとおりです。

図3 オプション43(要求時)構造
フィールド名サイズ [byte]説明
1st Suboption Code1サブオプション番号0x01
1st Suboption Len1第1サブオプションの長さ0x14
1st Suboption Data20証明書フィンガープリント可変
2nd Suboption Code1サブオプション番号0x02
2nd Suboption Len1第2サブオプションの長さ0x80
2nd Suboption Data128KPの前半128byte可変
表4 オプション43(要求時)の各フィールド説明

(2) ― 2 オプション125仕様

本オプションには、企業識別番号並びにKPの後半部分が含まれます。データ構造並びに各値(独自研究)は以下のとおりです。

図4 オプション125構造
フィールド名サイズ [byte]説明
Enteerprise Number4企業識別番号0x00 00 01 37
Data Len1本フィールド以降の長さ0x82
Suboption Code1サブオプション番号0x01
Suboption Len1サブオプションの長さ0x80
Suboption Data128KPの後半128byte可変
表5 オプション125の各フィールド説明

パケット仕様 (3) ― NKPU応答時のオプション

NKPU応答時は、オプション43(とオプション60)が必要となります。オプション43にはキープロテクターレスポンス(KPR)が含まれ、そのデータ構造並びに各値(独自研究)は以下のとおりです。

図5 オプション43(応答時)構造
フィールド名サイズ [byte]説明
Suboption Code1サブオプション番号0x02
Suboption Len1サブオプションの長さ0x3C
Suboption Data60KPR可変
表6 オプション43(応答時)の各フィールド説明

ここまでで、サーバ側のエミュレートに必要な情報は揃いました。次回はクライアント側の設定について確認していきます。

BitLocker適用下のWOL (1) – 概要と事前準備

はじめに

出先からリモートデスクトップで作業可能なことは、デスクトップPCの利点の一つと言えます。Wake On LAN (WOL)へ対応すれば、必要なタイミングで出先から電源を入れることができ、電気代も最小限に抑えることができるでしょう。
一方で、BitLockerにて起動時のPIN入力を有効化している場合、WOLのみでは暗号化解除ができず、PCを起動させることができません。
今回はWOL送信用のデバイスにて、Windows Serverで使用可能なBitLocker ネットワークロック解除機能をエミュレートし、PIN有りBitLocker環境における遠隔での電源投入を実現します。

システム構成

構成は極めてシンプルです。24/365のデバイス (今回はNASを利用) をサーバ側とし、WOLのMagic PacketとBitLockerネットワークロック解除プロトコル1を扱えるプログラムを置きます。


このプログラムはを実行すると、Magic Packetを送信した後NKPUの受信待ちをします。PCはMagic Packetにより起動した後、NKPUでBitLockerを解除し、無事立ち上がるというわけです。

証明書の用意

まずは使用する証明書を用意します。
幸い Microsoft Learn にて証明書の詳細パラメータが紹介されていますので、これに則って作成しました。
概ね以下のパラメータに気を付ければよさそうです(2023/10時点)。

  • 秘密鍵長:2048bit
  • 署名アルゴリズム:SHA512
  • キー使用法:keyEncipherment
  • 拡張キー使用法:1.3.6.1.4.1.311.67.1.1

参考まで、OpenSSLでの発行手法を載せておきます。

#秘密鍵生成
openssl genrsa -aes512 -passout pass:hogehoge -out BitLocker.key 2048

# 署名要求作成
openssl req -batch -new -key BitLocker.key -out BitLocker.csr -subj "/CN= BitLocker Network Unlock"

# 自己署名
openssl x509 -req -in BitLocker.csr -signkey BitLocker.key -sha512 -days 365 -out BitLocker.crt -extfile Option.txt -outform DER

なお、使用した拡張情報ファイル Option.txt の内容は以下の通りです。

keyUsage = keyEncipherment
extendedKeyUsage = 1.3.6.1.4.1.311.67.1.1
subjectKeyIdentifier = hash

事前準備はこのあたりでおしまいです。
次回以降、NKPUのエミュレートを中心に記載します。