スキップしてメイン コンテンツに移動

iPXE経由で iSCSI root にて Debian を セキュアブート

セキュアブートに対応した iPXE バイナリは公式サイトにはないのですが、調べていると サイン済みのバイナリが broadcom 社の KB に あると ipxe.org の bbs に記載がありました。該当の kb はこちらです。早速、この kb にリンクのある "64bit_ipxe_efi.zip" をブラウザでダウロードし、tftp/http サーバー上で解凍、dhcp サーバを設定して、tftp で取得・起動させた所、起動はするものの次のステージへは、特定のhttp ポート ( 4433 ) の固定パス ( Altiris/iPXE/GetPxeScript.aspx ) を参照するため、何もしていないと connection がリセットされてしまいます。
なので、apache2を 4433でもリッスンするようにして Altiris/iPXE/GetPxeScript.aspx を配置し、中身を shell が起動するだけの menu.ipxe にしたところ、シェルに入れました。これでOKだと思ったのですが、実はここからが難題でした。
というのも、サイン済みの bootnetx64.efi や linux カーネルをブートしようとしても、exec format error になり起動できません。機種によっては wimboot すら起動しません。それでも CDぐらいはブートできるだろうと思い直し、インストーラの iso ファイルの起動を sanboot コマンドにて試してみたところ、起動はするものの今度はインストーラまで到達できません。ただ、grubとカーネルまでは起動はしているので、iso ファイルを自前で作成し、前回のように nfsroot で立ち上げた所、システムも起動できましたが、isoファイルの作成だと grubのメニュー項目が read only なので、編集したい場合は iso ファイルを再作成しなければならず、実用的ではないなとこれはボツネタにしました。
そこで気を改めて r/w 可能な iSCSI で試してみることにしました。まず、始めは netinst cd イメージを targetcli で エクスポートした所、isoファイルの sanboot とほぼ同じで、grubとカーネルまでは起動できますが、cdromのマウントができない旨でインストール処理を続行することができませんでした。
ここで発想をかえて、grub からカーネルの起動まではできているので、iSCSI ターゲット上で ディスクイメージファイルを作成し、これを nbd デバイスとして割当ててマウントし、必要なものを grub-install や debootstrapで用意してから起動した所、無事 iPXE経由で Debianをセキュアブートできるようになりました。これで disk image file の書込もでき、grub メニューの変更も比較的簡単にできるので、本稿を挙げてみることにしました。
前置きが長くなりましたが、以下設定です。
# 必要なパッケージのインストールとファイルの準備 ( on tftp/http server 10.1.1.50 i50)
apt-get install tftpd-hpa apache2 unzip

cd /srv/tftp
mkdir ipxe-signed
cd ipxe-signed
# 上述の kb にある zipファイルをここに解凍。
unzip ~/ダウンロード/64bit_ipxe_efi.zip

cd /srv/tftp
wget https://ftp.debian.org/debian/dists/stable/main/installer-amd64/current/images/netboot/netboot.tar.gz
tar xzpf netboot.tar.gz
最低限必要なファイルは以上です。続いて必要なパッケージをインストールし disk image file を作成して targetcli を設定し disk image にアクセスできるようにしておきます。
# on iscsi target( on 10.1.1.106 sv106)
apt-get install qemu-nbd dosfstools xfsprogs grub-efi-amd64-signed debootstrap
modprobe -av nbd

mkdir -p /srv/
cd /srv/deb01

dd if=/dev/zero of=deb10.disk.img bs=1024k count=32768
dd if=/dev/zero of=deb11.disk.img bs=1024k count=32768
dd if=/dev/zero of=deb12.disk.img bs=1024k count=32768

##  targetcli start ( deb12.disk.img )
targetcli
cd /backstores/fileio
create deb12-amd64-01 /srv/deb01/deb12.disk.img
cd /iscsi
create iqn.1868-01.com.example:sv106.deb12-amd64-01
cd iqn.1868-01.com.example:sv106.deb12-amd64-01/tpg1/luns
create /backstores/fileio/deb12-amd64-01
cd ../acls
create iqn.1868-01.com.example:ft01
cd /
saveconfig
exit
## targetcli end
続いて disk image のパーティション(p1=ESP:vfat, p2=root:xfs)を設定しフォーマットしておきます。
# on iscsi target( on 10.1.1.106 sv106)

NBD=nbd12
DEB=deb12
HN=${DEB}a

qemu-nbd --format=raw --connect=/dev/${NBD} /srv/deb01/${DEB}.disk.img

fdisk /dev/${NBD}
############################
g
n
enter
enter
1050623

t
uefi

n
enter
enter
enter

w
############################

mkfs.vfat /dev/${NBD}p1

# debian 10 の場合
# mkfs.xfs -m crc=0,finobt=0 -f /dev/${NBD}p2
# debian 12 の場合
mkfs.xfs -f /dev/${NBD}p2
続いて 必要最小限の grub の設定を行います。
# on iscsi target( on 10.1.1.106 sv106)
P1_UUID=`lsblk -f /dev/${NBD}p1 | grep ${NBD}p1 | awk '{print $4}'`
P2_UUID=`xfs_admin -u /dev/${NBD}p2 | cut -d' ' -f 3`

mount /dev/${NBD}p2 /mnt
mkdir -p /mnt/boot/efi
mount /dev/${NBD}p1 /mnt/boot/efi

cd /mnt/boot/efi
mkdir -p /mnt/boot/efi/EFI/debian
scp 10.1.1.50:/srv/tftp/debian-installer/amd64/bootnetx64.efi  /mnt/boot/efi/EFI/debian/

cat > /mnt/boot/efi/EFI/debian/grub.cfg <<EOF
search.fs_uuid $P2_UUID root hd0,gpt2
set prefix=(\$root)/boot/grub
configfile \$prefix/grub.cfg
EOF

grub-install --target=x86_64-efi --efi-directory=/mnt/boot/efi --boot-directory=/mnt/boot --uefi-secure-boot /dev/${NBD}
システムがインストールされていなくても、ここまでで grub のシェルが立ち上がるようになります。(一旦ここで iSCSIからブートしてみると良いかもしれません。)
続いて grubのメニューを設定しておきます。
# on tftp/http server 10.1.1.50 i50
mkdir -p /mnt/boot/grub

cat > /mnt/boot/grub/grub.cfg <<EOF
menuentry 'Debian 10 iSCSI root'{
	linux /vmlinuz root=UUID=$P2_UUID rw ip=::::::dhcp iscsi_auto rootfstype=xfs rootwait
	initrd /initrd.img
}
EOF
続いてシステムを populate していきます。
# on iscsi target ( 10.1.1.106 sv106 )
cd /mnt

# debian 10 busterの場合
# debootstrap buster .

# debian 12 boookworm の場合
debootstrap bookworm .
つづいて、debootstrap では足りないパッケージ等を半自動でインストール・設定します。

cat > root/and-so-on.sh <<EOF
apt-get install -y --no-install-recommends linux-image-amd64 dbus busybox xfsprogs openssh-server open-iscsi zstd
apt-get install -y --no-install-recommends locales console-setup xterm fbterm fonts-vlgothic fonts-courier-prime
# set root password
passwd
# add user
adduser YourUserName
# change hostname
echo deb12a > /etc/hostname
# add ipv4 nameservers
echo nameserver 10.1.1.64 >> /etc/resolv.conf
echo nameserver 10.1.1.65 >> /etc/resolv.conf
# setup locales
dpkg-reconfigure locales
# setup keyboard layout
dpkg-reconfigure keyboard-configuration
exit
EOF

mount -t proc proc proc/
mount -t sysfs sysfs sys/
chroot . bash root/and-so-on.sh
umount proc/
umount sys/

cd /root
umount /mnt/boot/efi
umount /mnt
iSCSIディスクのセットアップは以上です。
次は、dhcpサーバを設定します。最初はkea-dhcpで行こうと思ったのですが、クライアントによっては boot file 名を正常に受け渡しできなかったので、isc-dhcp-serverで設定しました。
# on tftp/http server 10.1.1.50 i50
apt-get install isc-dhcp-server

# /etc/dhcp/dhcpd.conf
allow booting;
allow bootp;

option iscsi-initiator-iqn code 203 = string;

option space pxelinux;
option pxelinux.magic code 208 = string;
option pxelinux.configfile code 209 = text;
option pxelinux.pathprefix code 210 = text;
option pxelinux.reboottime code 211 = unsigned integer 32;

set vendorclass = option vendor-class-identifier;
option pxe-system-type code 93 = unsigned integer 16;
set pxetype = option pxe-system-type;

default-lease-time 600;
max-lease-time 7200;

ddns-update-style none;
authoritative;
log-facility-local7;

subnet 10.1.1.0 netmask 255.255.255.0 {
  option domain-name-servers 10.1.1.64, 10.1.1.65;
  option domain-name "example.com";
  option routers 10.1.1.23;
  option broadcast-address 10.1.1.255;
  next-server 10.1.1.50;
  if substring(vendorclass, 0, 9)="PXEClient" {
    if pxetype=00:06 or pxetype=00:07 {
        filename "ipxe-signed/ipxe.efi";
#        filename "ipxe-signed/snponly.efi";
    } else {
        filename "pxelinux/pxelinux.0";
    }
  }  
  pool {
    range 10.1.1.180 10.1.1.250;
  }
}

host ft01 {
  hardware Ethernet e4:7f:b2:16:e0:58;
  fixed-address 10.1.1.172;
  next-server 10.1.1.50;
  filename "ipxe-signed/ipxe.efi";
#  filename "ipxe-signed/snponly.efi";
  option host-name "ft01";
}
つづいて、http server(10.1.1.50 i50)の設定をおこないます。
# on http server (10.1.1.50 i50)
apt-get install apache2

cat > /etc/apache2/sites-available/ipxe-1-4433.conf <<EOF
<VirtualHost 10.1.1.50:4433>
	ServerAdmin webmaster@example.com
	DocumentRoot /srv/tftp

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

	<Directory />
        	Options +FollowSymLinks +Indexes
        	Require all granted
	</Directory>
</VirtualHost>
EOF

cat > /etc/apache2/sites-available/ipxe-1.conf <<EOF
<VirtualHost 10.1.1.50:80>
	ServerAdmin webmaster@example.com
	DocumentRoot /srv/tftp

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

	<Directory />
        	Options +FollowSymLinks +Indexes
        	Require all granted
	</Directory>
</VirtualHost>
EOF

cat > /etc/apache2/ports.conf <<EOF
# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default.conf

Listen 80
Listen 4433

<IfModule ssl_module>
	Listen 443
</IfModule>

<IfModule mod_gnutls.c>
	Listen 443
</IfModule>
EOF
Debian/Ubuntuの場合、config の 有効化・無効化は a2ensite/a2dissiteコマンドでできますので、そちらを使ってみてください。なおポートの設定を追加している為、systemctl restart apache2 で apache2 の再起動が必要です。
最後に /srv/tftp/Altiris/iPXE/GetPxeScript.aspx ( 中身は menu.ixpe 相当) の例です。
# on tftp/http server ( 10.1.1.50 i50 )

#!ipxe

:start

menu MENU
item --gap --					---------------------------------------------------------------
item deb10-amd64-01-iscsi       deb10-amd64-01 iscsi root
item deb11-amd64-01-iscsi       deb11-amd64-01 iscsi root
item deb12-amd64-01-iscsi       deb12-amd64-01 iscsi root
item --gap --					---------------------------------------------------------------
item shell						iPXE shell
item --gap --					---------------------------------------------------------------
choose selected
goto ${selected}

:deb10-amd64-01-iscsi
set keep-san 1
set initiator-iqn iqn.1868-01.com.example:${hostname}
set root-path iscsi:10.1.1.106::::iqn.1868-01.com.example:sv106.deb10-amd64-01
sanboot --drive 0x80 --filename \EFI\debian\bootnetx64.efi ${root-path}
goto start

:deb11-amd64-01-iscsi
set keep-san 1
set initiator-iqn iqn.1868-01.com.example:${hostname}
set root-path iscsi:10.1.1.106::::iqn.1868-01.com.example:sv106.deb11-amd64-01
sanboot --drive 0x80 --filename \EFI\debian\bootnetx64.efi ${root-path}
goto start

:deb12-amd64-01-iscsi
set keep-san 1
set initiator-iqn iqn.1868-01.com.example:${hostname}
set root-path iscsi:10.1.1.106::::iqn.1868-01.com.example:sv106.deb12-amd64-01
sanboot --drive 0x80 --filename \EFI\debian\bootnetx64.efi ${root-path}
goto start

:shell
echo Type 'exit' to get back to the menu
shell
set menu-timeout 0
goto start
設定は以上です。以下起動後の dmesg の一部です。
--snip
[    0.000000] Command line: BOOT_IMAGE=/vmlinuz root=UUID=5b540e35-9157-4c61-be1e-xxxxxxxxxxxx rw ip=::::::dhcp iscsi_auto rootfstype=xfs rootwait
--snip
[    0.000000] secureboot: Secure boot enabled
本来ならiPXE.orgが公式で signed バイナリをだしていればよいのですが、サイン済みの iPXE バイナリがあるにはあるので、いつかは出てくるかもしれませんね。
長くなりましたが、今回は以上です。それでは。

コメント

このブログの人気の投稿

wsdd を使ってSamba サーバをネットワークに表示

Windows 10のアップデートで、セキュリティー対応のため、smbv1がデフォルトではインストールされなくなり、Samba serverがエクスプローラーのネットワークに表示されなくなってしまいました。そこで、いくつか方法を調べたのですが、linuxでwsdの実装がないか探したところ、 https://github.com/christgau/wsdd が、見つかりましたので、さっそくインストールしてみました。まだパッケージにはないようですが、インストール自身は簡単です。wsdd自体は以下のように取得し、linkを張っておきます。 cd /usr/local/bin/ sudo wget https://raw.githubusercontent.com/christgau/wsdd/master/src/wsdd.py sudo chmod 755 wsdd.py sudo ln -sf wsdd.py wsdd こちらのsambaサーバはDebianなので、/etc/systemd/system/wsdd.serviceは以下のようにしました。 [Unit] Description=Web Services Dynamic Discovery host daemon Requires=network-online.target After=network.target network-online.target multi-user.target [Service] Type=simple ExecStart=/usr/local/bin/wsdd -d MYDOMAIN [Install] WantedBy=multi-user.target wsdd -d MYDOMAINのところを、環境にあわせて書き換えてください。 次に、systemdに登録・起動テストを行います。 systemctl enable wsdd systemctl start wsdd 起動に成功すると、エクスプローラーのネットワークに表示されます。  なおこのwsddはpython3が必要です。一度試してみてください。SMBv1/CIFSを停止していても、大丈夫です。 cで書かれたほかのwsddの実装もあるようなので、いずれパッケージになるかも...

Windows デバイス暗号化 のサポートで "許可されていない dma 対応バス/デバイスが検出されました"の対処

Windows でセキュリティー関係を見ているのですが、とあるPCでmsinfo32で確認すると"デバイス暗号化のサポート"で"許可されていない dma 対応バス/デバイスが検出されました"と出ていました。このPCの場合、それ以外はOK(なにも表示されない)だったのですが、ネットでしらべるとMSのドキュメントではハードウェアベンダーに問い合わせるなどと敷居が高く具体的にどこが引っかかっているかわかりません。そこでほかに方法はないかとしらべやってみたところ、"前提条件をみたしています"まで持って行けたので、本稿を挙げた次第です。 具体的には、以下のようにします。 1-a. 許可するDMA対応バス・デバイスを指定するレジストリの所有権と書き込み設定をおこなう。 以下のレジストリキーの所有者を自分自身(管理ユーザ)のものにし、フルコントロール権を付与する。 HKLM\SYSTEM\CurrentControlSet\Control\DmaSecurity\AllowedBuses もしくは 1-b. MicrosoftよりPsExecをダウンロードし、System権限でRegeditを立ち上げ編集する。 Microsoftより、https://docs.microsoft.com/en-us/sysinternals/downloads/psexec にある こちら をダウンロードし、解凍する。解凍すると、x64の場合、PsExec64.exeがあるので、管理者権限で以下を実行し、システム権限でregeditを立ち上げることが出来るようになる。 cd Downloads\PSTools .\PsExec64.exe -sid C:\Windows\regedit.exe 2-a. パワーシェルスクリプトを実行し、PnPデバイスのうちインスタンスがPCIで始まるものを"AllowedBuses"に追加する。 以下のパワーシェルスクリプトを作成する。たとえばDocuments\allow-dma-bus-device.ps1として作成する。( こちらの記事のものを使用させていただきました: Thank you! ) $tmpfile = "$($env:T...

フレッツ光クロス:MAP-E ROUTER by Debian Box (iptables)

フレッツ光クロスがようやく開通したので、Debianにてrouterを構成し接続してみました。なお、プロバイダーを選ぶにあたっては、IPoE方式がそれぞれ異なるため検討したところ、IPoEでは、MAP-Eでもv6plusとocnバーチャルコネクトがあり、前者がポート数240なのに対し、後者は約4倍のポート数が使えるようなネットの情報をみて、OCNバーチャルコネクトを選択しました。(プロバイダーとしてはぷららです。なおDS-LiteはCE側でのNATではないので今回は見送りました。)そこで、OCN バーチャルコネクトをDebian(iptables)で実現するとどうなるかと思い、ネットの情報を頼りにしつつ、設定した次第です。 実際に試した結果、とりあえず通信できていますが、MAP-Eは本来マッピングルールをマップサーバから取得するはずなので、今回のやり方が正解とはいえませんし、仕様変更されると通信できなくなる可能性があります。あくまでも参考程度ですが、本稿をUPしてみました。 2023/03/16追記: こちら にゲームコンソールNAT越え(Nintendo Switch ナットタイプ A判定)対応版を投稿しました。 2023/03/28追記:※1の記述および3行無効化によりNAT越え(Nintendo Switch ナットタイプ B判定)できるようになりました。 構成は以下の通りです。 ルーターがDebianで回線がOCNバーチャルコネクトであること以外はなにも特別なところはない構成です。 さて、いきなり設定ですが、まず、割り当てられたプレフィックスを確認します。 確認は、 dhclient -6 -d -P enp2s0 とします。出力の中に 前略 RCV: | | X-- IAPREFIX 2400:4050:5c71:af00::/56 後略 このようにプレフィックスが表示されるので、その確認したプレフィックスを書き留めておきます。これを こちらで 入力します。すると、 CE: 2400:4050:5c71:af00:99:f171:c600:2f00 IPv4 アドレス: 153.241.113.198 ポート番号:(1776-1791 2800-2815 3824-3839) 4848-4863 5872-5887 6896-...