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

ConnectX-4 VPIを使い ipoib + iPXE にて Debian 12 を iSCSI root で セキュアブート

ファームウェアを 2025/03 現在で最新のものにアップデートした ConnectX-4 VPI は、Flexboot が UEFI に対応しているとのこですが、当方の環境では ConnectX-3 VPI が BIOS モードで立ち上がるような CUI は 立ち上がらず、また、BIOSでも設定項目はみつかりませんでした。その代わり、サーバ上で Networking stack を Enabled にして iPXEではなくPXEブートする方法では確かにPXEパケットはやり取りできています。(参考までにCX3ではブートメニューに現れませんでした。こちらの uefi rom を焼いたところ、CX3 もブートメニューに現れました。)
しかし、iPXEではなくPXE ブートでは iSCSI 接続を iBFT として登録する方法はBIOS上で設定項目がない限りありません。そこで、PXEから bootfileを signed ipxe.efi にし、 sanhook で iscsi root イメージを ibft に登録してからブートしたところ、今度は上手く行きました。(2025/04/05:訂正:当方のapache2 の コンフィグミスで、signed ipxe.efiにて直接 IPoIB 経由で Altiris/iPXE/GetPxeScript.aspx (menu.ipxe相当)にアクセスできましたので、表題および本文を訂正しました。)
基本的には iPXE経由でセキュアブートする方法とあまり違いはありませんが、(2025/04/07 大幅加筆修正:)こちらでも詳細を挙げておくことにしました。
# iscsi root memo 01

#### disk image の作成等
# on target i50 ( ubuntu 24.04 )
apt-get install targetcli-fb qemu-utils tftpd-hpa apache2 isc-dhcp-server

REL=bookworm
IMG=deb12.amd64.01.img
tNAME=deb12-amd64-01
tHOSTNAME=i50
tADDR=10.1.40.50
tBASE=iqn.1868-01.com.example
iHOSTNAME=sv112
NBD=nbd0
MP=/media/${tNAME}
SRV=/srv/deb02

mkdir -p ${SRV}
cd ${SRV}

dd if=/dev/zero of=${IMG} bs=1024k count=32768

modprobe -av nbd
qemu-nbd -f raw -c /dev/${NBD} /$SRV/${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

P2_UUID=`xfs_admin -u /dev/${NBD}p2 | cut -d' ' -f 3`

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

cd ${MP}/boot/efi
mkdir -p ${MP}/boot/efi/EFI/debian

cd ${SRV}
mkdir -p netboot
cd netboot
wget https://ftp.debian.org/debian/dists/stable/main/installer-amd64/current/images/netboot/netboot.tar.gz
tar xzpf netboot.tar.gz

cp -a debian-installer/amd64/bootnetx64.efi ${MP}/boot/efi/EFI/debian/

cat > ${MP}/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

cd ${MP}
debootstrap ${REL} .

# debootstrap では足りないパッケージ等を半自動でインストール・設定
cat > root/and-so-on.sh <<EOF
apt-get install -y --no-install-recommends linux-image-amd64 busybox xfsprogs openssh-server open-iscsi dbus zstd grub-efi-amd64
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 ${tNAME} > /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 console
dpkg-reconfigure console-setup
# setup keyboard layout
dpkg-reconfigure keyboard-configuration
exit
EOF

cd ${MP}
mount -t proc proc proc/
mount -t sysfs sysfs sys/
mount --rbind /dev dev/
chroot . bash root/and-so-on.sh

grub-install --target=x86_64-efi --efi-directory=/boot/efi --boot-directory=/boot --uefi-secure-boot

exit 

cd $MP/boot

KVER=`ls vmlinuz-*-amd64 | sed 's/vmlinuz-//g' | sed 's/-amd64//g'`

cat > ${MP}/boot/grub/grub.cfg <<EOF
serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1
terminal_input --append "console serial"
terminal_output --append "console serial"
 
set default="0"
set timeout=20

menuentry 'Debian iSCSI root ( ${KVER} )'{
	linux /boot/vmlinuz-${KVER}-amd64 root=UUID=$P2_UUID rw ip=:::::ib0:dhcp iscsi_auto net.ifnames=0 rootfstype=xfs rootwait console=tty0 console=ttyS0,115200n8
	initrd /boot/initrd.img-${KVER}-amd64.iscsi
}

EOF

mkdir -p /srv/tftp/boot
cp -a ${MP}/boot/*${KVER}* /srv/tftp/boot/ 

#### ターゲット設定 #### */
targetcli /backstores/fileio create ${tNAME} ${SRV}/${IMG}
targetcli /iscsi create ${tBASE}:${tHOSTNAME}.${tNAME}
targetcli /iscsi/${tBASE}:${tHOSTNAME}.${tNAME}/tpg1/luns create /backstores/fileio/${tNAME}
targetcli /iscsi/${tBASE}:${tHOSTNAME}.${tNAME}/tpg1/acls create ${tBASE}:${iHOSTNAME}
targetcli / saveconfig

################################################################
#### apache2の設定
apt-get install apache2

cat > /etc/apache2/sites-available/ipxe-40.conf <<EOF
<VirtualHost ${tAddr}:80>
	ServerAdmin webmaster@localhost
	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-40-4433.conf <<EOF
<VirtualHost 10.1.40.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
a2dissite 000-default
a2ensite ipxe*

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

systemctl restart apache2

###################################################
# dhcp サーバーの設定

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

option user-class code 77 = string;
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.40.0 netmask 255.255.255.0 {
  option domain-name-servers 10.1.1.64;
  option domain-name "example.com";
  option routers 10.1.40.50;
  option broadcast-address 10.1.40.255;
  next-server 10.1.40.50;
  if exists user-class and option user-class = "iPXE" {
    filename "menu.ipxe";
  } else {
    if pxetype=00:06 or pxetype=00:07 {
      filename "ipxe-signed/ipxe.efi";
#      filename "ipxe-signed/snponly.efi";
#      filename "ipxe-unsigned/snponly.efi";
#      filename "ipxe-unsigned/ipxe.efi";
    } elsif pxetype=00:00 {
      filename "ipxe.pxe";
    }
  }
  pool {
    range 10.1.40.200 10.1.40.250;
  }
}

host sv112 {
  option host-name "sv112";
  hardware ethernet 00:11:22:33:01:12;
  fixed-address 10.1.40.112;
}

# check config and restart dhcp server
dhcpd -t  
systemctl restart isc-dhcp-server
###################################################
#### tftp serverの設定
apt-get install unzip

cd /srv/tftp

# singed ipxe.efi ( 64bit_ipxe_efi.zip ) をブラウザでダウンロードし、解凍
mkdir ipxe-signed
cd ipxe-signed
unzip ../64bit_ipxe_efi.zip

## menu.ipxe (Altiris/iPXE/GetPxeScript.aspx) の設定
cat > /srv/tftp/Altiris/iPXE/GetPxeScript.aspx <<EOF
#!ipxe

:start
menu                    			MENU
item --gap --           			--------------
item iSER-${tHOSTNAME}.${tNAME}	iSER root ( ${tHOSTNAME}.${tNAME}.iser )
item --gap --           			--------------
item shell              			Drop to iPXE shell
item --gap --           			--------------
choose selected
goto \${selected}

:iSER-${tHOSTNAME}.${tNAME}
set initiator-iqn ${tBASE}:\${hostname}
set root-path iscsi:${tAddr}::::${tBASE}:${tHOSTNAME}.${tNAME}
sanboot --drive 0x80 --filename \EFI\debian\bootnetx64.efi \${root-path} || goto shell
goto start

:shell
echo Type 'exit' to get back to the menu
shell
set menu-timeout 0
goto start

EOF

cd /srv/tftp
ln -sf Altiris/iPXE/GetPxeScript.aspx menu.ipxe

################################################
#### initramfs-toolsの設定その1(chroot下)
cd ${MP}
chroot .

cat >> /etc/initramfs-tools/modules <<EOF

ib_core
ib_cm
ib_uverbs
ib_umad
iw_cm
rdma_cm
rdma_ucm
mlx4_core
mlx4_ib
mlx5_core
mlx5_ib
ib_mthca
ib_ipoib

iscsi_ibft

EOF
###################################################
#### initramfs-toolsの設定その2(chroot下)
# /usr/share/initramfs-tools/scripts/local-top/iscsi の変更 

mkdir -p /root/initrd_iscsi
cd /root/initrd_iscsi

cp -a /usr/share/initramfs-tools/scripts/local-top/iscsi iscsi.orig
cp -a /usr/share/initramfs-tools/scripts/local-top/iscsi iscsi

# save as iscsi-iscsi.patch
## -----------------------------------------------------------
--- iscsi.orig	2025-03-18 07:16:13.081164264 +0900
+++ iscsi		2025-03-26 22:37:00.263868546 +0900
@@ -99,7 +99,7 @@
 		# try to auto-configure network interface based
 		# on firmware values
 		modprobe iscsi_ibft
-		iscsistart -N
+		iscsistart -N || echo "Unable to configure network"
 
 		# write out /run/net-$IFACE.conf based on what
 		# was in the firmware
@@ -182,7 +182,7 @@
 	# also, if we set up DHCP iBFT, we need ipconfig to run so it creates
 	# a proper /run/net-${DEVICE}.conf file that includes the DNS search
 	# domain, which we don't get in our iBFT data (see LP: #1806777)
-	configure_networking
+	true || configure_networking
 
 	if [ -n "$IBFT_DHCP_DEVICE" ]; then
 		if ! [ -e "/run/net-${DEVICE}.conf" ] ; then
@@ -192,7 +192,7 @@
 			# though that will not include the DNS search domain
 			mv "/run/net-${DEVICE}.conf.ibft" "/run/net-${DEVICE}.conf"
 			# need to re-run configure_networking to process conf file
-			configure_networking
+			true || configure_networking
 		fi
 	fi
 
@@ -330,8 +330,58 @@
 	exit 0
 fi
 
+DEVICE=`echo $ip | cut -d: -f 6`
+iscsistart -f | grep -v \# > /run/iscsi-vars
+iface=`cat /run/iscsi-vars | grep iface.net_ifacename | cut -d' ' -f3`
+
+if [ "$iface" == "$DEVICE" ]; then
+  iscsistart -N || echo Failed to bring up the network as specified by iBFT
+else
+  i=$DEVICE
+  if [ -e /sys/class/net/$i/carrier ]; then
+    ip link set dev $i up && interface_up=`cat /sys/class/net/$i/carrier`
+  else
+    interface_up=""
+  fi
+  echo awainting for interface $i up
+  count=0
+  while [ "$interface_up" == "0" -o ! -n "$interface_up" ] && [ $count -lt 30 ]
+  do
+    echo interface_up: $interface_up
+    if [ -e /sys/class/net/$i/carrier ]; then
+      ip link set dev $i up && interface_up=`cat /sys/class/net/$i/carrier`
+    else
+      interface_up=""
+    fi
+    if [ "$interface_up" == "1" ];then
+      echo $i is up
+    fi
+    count=$((count + 1))
+    sleep 1
+  done
+
+  address=`cat /run/iscsi-vars | grep iface.ipaddress | cut -d' ' -f3`
+  netmask=`cat /run/iscsi-vars | grep iface.subnet_mask | cut -d' ' -f3`
+  gateway=`cat /run/iscsi-vars | grep iface.gateway | cut -d' ' -f3`
+  plength=`cat /run/iscsi-vars | grep iface.prefix_len | cut -d' ' -f3`
+  dns=`cat /run/iscsi-vars | grep iface.primary_dns | cut -d' ' -f3`
+   
+  ip addr del $address/$plength dev $iface
+  ip addr add $address/$plength dev $DEVICE
+  ip rout add default via $gateway
+
+  initiatorname=`cat /run/iscsi-vars | grep iface.initiatorname | cut -d' ' -f3`
+  targetname=`cat /run/iscsi-vars | grep node.name | cut -d' ' -f3`
+  targetaddr=`cat /run/iscsi-vars | grep node | grep address | grep 0 | cut -d' ' -f3`
+  iscsistart --param iface.net_ifacename=ib0 -i $initiatorname -g 1 -t $targetname -a $targetaddr || true
+fi 
+
 do_iscsi_login
 
+if [ "$iface" != "$DEVICE" ]; then
+  ip addr del $address/$plength dev $iface
+fi
+
 udevadm settle
 
 # The second check is to allow us to use multiple root= parameters. That way##
## -----------------------------------------------------------

apt-get install patch

patch < iscsi-iscsi.patch

cp -a iscsi /usr/share/initramfs-tools/scripts/local-top/iscsi

###################################################
#### initrd.imgの生成(chroot下)

cd /root/initrd_iscsi

KVER=`cd /boot && ls vmlinuz-*-amd64 | sed 's/vmlinuz-//g' | sed 's/-amd64//g'`

cat > updt-${KVER}.sh <<EOF
update-initramfs -k ${KVER}-amd64 -c -b .
mv initrd.img-${KVER}-amd64 initrd.img-${KVER}-amd64.iscsi
cp initrd.img-${KVER}-amd64.iscsi ${MP}/boot
EOF
chmod +x updt-${KVER}.sh
./updt-${KVER}.sh

##############################################
# 後片付け
# exit from chrooted env and clean up
exit

cd ${MP}
umount proc/
umount sys/
mount -o remount --make-rslave dev/
umount -R dev/

cd

umount ${MP}/boot/efi
umount ${MP}

qemu-nbd -d /dev/${NBD}
参考までに mstflint を使った ファームウェア(cx4-firmware.binが対象の場合)の更新は以下の通りです。
mstflint -d 18:00.0 -i cx4-firmware.bin -allow_psid_change burn
# 再起動後、mstconfig にて UEFI を有効にする
mstconfig -d 18:00.0 set EXP_ROM_UEFI_x86_ENABLE=True UEFI_HII_EN=True
# 今一度再起動して、boot device に ConnectX-4 が含まれていることを BIOS で確認
また、flexboot を更新する場合は、以下のようになります。
# 確認
mstflint -d 18:00.0 q
--snip
Rom Info:              type=UEFI version=14.21.17 cpu=AMD64,AARCH64
                       type=PXE version=3.6.102 cpu=AMD64
--snip

# バックアップ
mstflint -d 18:00.0 rrom CX4-14.21.17.efirom

# ファイルの取得、解凍
wget https://www.mellanox.com/downloads/Drivers/FlexBoot-3.6.204_4115_14_22_14_RELEASE_X64_AARCH64_0x1013.zip
unzip FlexBoot-3.6.204_4115_14_22_14_RELEASE_X64_AARCH64_0x1013.zip

# 更新
mstflint -d 18:00.0 --allow_rom_change brom FlexBoot-3.6.204_4115_14_22_14_RELEASE_X64_AARCH64_0x1013.efirom
以前にも書いたのですが、iPXEから公式の signed ipxe.efi がでれば良いですね。
今回は以上です。それでは。

コメント

このブログの人気の投稿

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-...