Romantic Irony

好きなこと・気になったことについて書いていきます!

VirtualBMC で VM をベアメタルライクに操作する

この記事は、呉高専 Advent Calendar 2022 の8日目として書きます。

今回は VirtualBMC という KVM ホスト上の仮想マシン(以下、VM) をあたかもベアメタルサーバかのように操作できるという Tips 的なツールを紹介したいと思います。

BMC

VirtualBMC の紹介に入る前に、そもそも BMC とは何でしょうか?

BMC ( Baseboard Management Controller ) とは IPMI 規格に基づいてベアメタルサーバ(いわゆる、物理サーバ)に組み込まれているハードウェアモジュールです。一般的にはエンタープライズレベルのサーバには BMC が組み込まれています。

あらかじめ BMC に設定を入れておくことで、ネットワーク越しにベアメタルサーバ内のハードウェアリソース(CPU、メモリ、など)の状態やサーバの温度を監視したり、サーバのコンソール画面をネットワークを通してまるごと転送することでグラフィカルコンソールを表示することができます。また、BMC の電源とベアメタルサーバ本体の電源は独立しているため、リモートサイトから BMC を通してサーバの電源操作を実施することもできます。

なお、BMC は IPMI 規格に基づいて設計されていることや、後ほど出てくる IPMI コマンドで操作できることからか 「IPMI デバイス」と呼ばれることもあります。また、通常は各ハードウェアベンダによって BMC のための独自のグラフィカルインターフェースが提供されており、ベンダによってその名称が異なるため多少混乱するかもしれませんが、基本的にはその実態は BMC であり機能も大きな差はないかと思います。

ハードウェアベンダごとに異なる BMC グラフィカルインターフェースの名称:

IPMI

今回は VirtualBMC を使用することを目的としているため、BMC の操作はグラフィカルインターフェースではなく ipmitool というコマンドラインクライアントを使用します。したがって、ipmitool の基本的な使い方を簡単に下記に記載しておきます。

(1) 基本的な引数
# ipmitool -I lanplus -H <IP address> -U <user> -P <password> <command>


(2) ベアメタルサーバの電源状態の確認
# ipmitool -I lanplus -H <IP address> -U <user> -P <password> power status


(3) 電源をオン
# ipmitool -I lanplus -H <IP address> -U <user> -P <password> power on


(4) 電源をオフ
# ipmitool -I lanplus -H <IP address> -U <user> -P <password> power off


(5) 次回起動時のブートデバイスを PXE に設定
# ipmitool -I lanplus -H <IP address> -U <user> -P <password> chassis bootdev pxe

VirtualBMC

github.com

これまでの説明からもわかるとおり、BMC はリモートサイトからベアメタルサーバの状態を監視または操作するためのものであるため、本来は仮想環境上の VM においては必要のない機能かと思います。

では、どういう場合に仮想環境において BMC が必要になるかというと、開発するソフトウェアもしくは使用するソフトウェアが IPMI 接続を前提としてサーバを操作する仕様となっている状況を想定してみてください。

そのようなソフトウェアの開発環境や検証環境においては、VM を通常のベアメタルサーバのように ipmitool コマンドを使用して操作できれば、別途ベアメタルサーバを用意しなくてよくなります。これは、開発者やソフトウェアの検証を実施したいエンジニアにとっては非常に助かります。


余談:


そもそも IPMI を扱うソフトウェアなんてあまり馴染みがないという方もいるかと思いますので少し紹介しておきます。

近年は AWSGCP、Azure などのパブリッククラウドが主流であり多くの方はそれらを使用されたことがあると思います。

このパブリッククラウドは、各クラウドベンダが提供するプラットフォーム上のリソースを不特定多数のユーザが共有して使用しているイメージです。

しかし、”パブリック”クラウドがあるということは、当然のその反対の「プライベートクラウド」も存在します。プライベートクラウドは、一般的にはとある会社内でのみで使用する独自のクラウドプラットフォーム(IaaS 基盤)を会社内のユーザ向けに提供するイメージです。

そして、それらの構築のために利用されるソフトウェア群として OpenStack というプロジェクトが存在します。このような IaaS 基盤を構成するソフトウェアは、構築にあたって多数のベアメタルサーバをオーケストレーションすることが求められるため、当然ながら BMC ないしは IPMI を通してそれらを操作することを前提としています。

そして、じつは今回紹介する VirtualBMC は OpenStack プロジェクトにおけるひとつの成果物でもあります。


VirtualBMC の動作

VirtualBMC の仕組みはシンプルで、VirtualBMC サービスが IPMI クライアントと VM が起動しているハイパーバイザ間の仲介役となり、ipmitool コマンドの内容をハイパーバイザ用の命令に変換しハイパーバイザに対して指示を出します。より正確には、ハイパーバイザの手前に libvirt というハイパーバイザの抽象化ライブラリが間に入ります。

VirtualBMC の動作イメージ
したがって、libvirt がサポートしているハイパーバイザであれば技術的には VirtualBMC を使用することができると思いますが、私自身は QEMU/KVM でしか試したことがありません。

デモ

ここからは、デモとともに VirtualBMC の具体的な使用方法について紹介していきたいと思います。

今回の検証環境は下記の通りとなります。

デモ環境のイメージ図

事前準備

(1) OS およびバージョンの確認
# cat /etc/redhat-release 
Red Hat Enterprise Linux release 8.4 (Ootpa)


(2) QEMU/KVM では CPU が Intel VT もしくは AMD-V に対応している必要があるため確認
# lscpu | grep -e vmx -e svm
Flags:               fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l3 cdp_l3 invpcid_single intel_ppin ssbd mba ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid cqm mpx rdt_a avx512f avx512dq rdseed adx smap clflushopt clwb intel_pt avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts pku ospke avx512_vnni md_clear flush_l1d arch_capabilities


(3) virtualization 関連のパッケージをインストール
# dnf module install -y virt


(4) その他の必要なツールをインストール
# dnf install -y libvirt virt-install virt-viewer libguestfs-tools-c


(5) kvm カーネルモジュールが導入されていることを確認
# lsmod | grep kvm
kvm_intel             315392  0
kvm                   847872  1 kvm_intel
irqbypass              16384  1 kvm


(6) libvirtd サービスを有効化および起動
# sudo systemctl enable --now libvirtd


以上で環境の事前準備は完了となります。

続いて、仮想ネットワーク br-integration を1つと、サーバの状態を確認する管理用VM mgmt と、管理される側のVM target という2つのVM作成していきます。 ipmitoolmgmt VM から実行する想定となります。


仮想ネットワークを作成

(1) 仮想ネットワークの初期状態を確認(default ネットワークは libvirt 起動時に作成される)
# virsh net-list
 Name      State    Autostart   Persistent
--------------------------------------------
 default   active   yes         yes


(2) br-integration ネットワークの定義ファイルを作成
# cat << EOF > br-integration.xml
<network>
  <name>br-integration</name>
  <bridge name='br-integration' zone="libvirt"/>
  <forward mode='nat'>
    <nat>
      <port start='1024' end='65535'/>
    </nat>
  </forward>
  <ip address='192.168.24.1' netmask='255.255.255.0'/>
</network>
EOF


(3) br-integration.xml からネットワーク定義をインポート
# virsh net-define br-integration.xml
Network br-integration defined from br-integration.xml


(4) br-integration ネットワークの自動起動を有効化
# virsh net-autostart br-integration
Network br-integration marked as autostarted


(5) br-integration ネットワークを起動
# virsh net-start br-integration
Network br-integration started


(6) 仮想ネットワークの状態を確認
# virsh net-list
 Name             State    Autostart   Persistent
---------------------------------------------------
 br-integration   active   yes         yes
 default          active   yes         yes


mgmt という名前で VM を作成

(1) mgmt という名前で 15GB の空のディスクイメージを作成
# qemu-img create -f qcow2 /var/lib/libvirt/images/mgmt.qcow2 15G
Formatting '/var/lib/libvirt/images/mgmt.qcow2', fmt=qcow2 size=16106127360 cluster_size=65536 lazy_refcounts=off refcount_bits=16


(2) RHEL8.4 イメージに含まれている /dev/sda3 パーティションを拡張しつつ、イメージを mgmt ディスクイメージにコピー
# virt-resize --expand /dev/sda3 /var/lib/libvirt/images/rhel-8.4-x86_64-kvm.qcow2 /var/lib/libvirt/images/mgmt.qcow2
[   0.0] Examining /var/lib/libvirt/images/rhel-8.4-x86_64-kvm.qcow2
**********

Summary of changes:

/dev/sda1: This partition will be left alone.

/dev/sda2: This partition will be left alone.

/dev/sda3: This partition will be resized from 9.9G to 14.9G.  The 
filesystem xfs on /dev/sda3 will be expanded using the ‘xfs_growfs’ 
method.

**********
[   3.3] Setting up initial partition table on /var/lib/libvirt/images/mgmt.qcow2
[  14.1] Copying /dev/sda1
[  14.2] Copying /dev/sda2
[  14.2] Copying /dev/sda3
 100% ⟦▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒⟧ 00:00
[  24.8] Expanding /dev/sda3 using the ‘xfs_growfs’ method

Resize operation completed with no errors.  Before deleting the old disk, 
carefully check that the resized disk boots and works correctly.


(3) mgmt イメージの root パスワードを設定し cloud-init パッケージをアンインストール
# virt-customize -a /var/lib/libvirt/images/mgmt.qcow2 --root-password password:password --uninstall cloud-init
[   0.0] Examining the guest ...
[   4.7] Setting a random seed
[   4.7] Setting the machine ID in /etc/machine-id
[   4.7] Uninstalling packages: cloud-init
[   5.9] Setting passwords
[   7.0] Finishing off


(4) 作成した mgmt イメージを使用して mgmt という名前で VM を起動
# virt-install --name mgmt --memory 1536 --vcpus 3 --disk /var/lib/libvirt/images/mgmt.qcow2 --import --os-variant rhel8.4 --network network=br-integration --noautoconsole

Starting install...
Domain creation completed.


(5) mgmt VM が起動していることを確認
# virsh list
 Id   Name   State
----------------------
 4    mgmt   running


target という名前で VM を作成

(1) target という名前で 15GB の空のディスクイメージを作成
# qemu-img create -f qcow2 /var/lib/libvirt/images/target.qcow2 15G
Formatting '/var/lib/libvirt/images/target.qcow2', fmt=qcow2 size=16106127360 cluster_size=65536 lazy_refcounts=off refcount_bits=16


(2) RHEL8.4 イメージに含まれている /dev/sda3 パーティションを拡張しつつ、イメージを target ディスクイメージにコピー
# virt-resize --expand /dev/sda3 /var/lib/libvirt/images/rhel-8.4-x86_64-kvm.qcow2 /var/lib/libvirt/images/target.qcow2
[   0.0] Examining /var/lib/libvirt/images/rhel-8.4-x86_64-kvm.qcow2
**********

Summary of changes:

/dev/sda1: This partition will be left alone.

/dev/sda2: This partition will be left alone.

/dev/sda3: This partition will be resized from 9.9G to 14.9G.  The 
filesystem xfs on /dev/sda3 will be expanded using the ‘xfs_growfs’ 
method.

**********
[   2.8] Setting up initial partition table on /var/lib/libvirt/images/target.qcow2
[  13.7] Copying /dev/sda1
[  13.7] Copying /dev/sda2
[  13.8] Copying /dev/sda3
 100% ⟦▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒⟧ 00:00
[  24.4] Expanding /dev/sda3 using the ‘xfs_growfs’ method

Resize operation completed with no errors.  Before deleting the old disk, 
carefully check that the resized disk boots and works correctly.


(3) mgmt イメージの root パスワードを設定し cloud-init パッケージをアンインストール
# virt-customize -a /var/lib/libvirt/images/target.qcow2 --root-password password:password --uninstall cloud-init
[   0.0] Examining the guest ...
[   4.7] Setting a random seed
[   4.7] Setting the machine ID in /etc/machine-id
[   4.7] Uninstalling packages: cloud-init
[   6.0] Setting passwords
[   7.1] Finishing off


(4) 作成した mgmt イメージを使用して mgmt という名前で VM を起動
# virt-install --name target --memory 1536 --vcpus 3 --disk /var/lib/libvirt/images/target.qcow2 --import --os-variant rhel8.4 --network network=br-integration --noautoconsole

Starting install...
Domain creation completed.


(5) target VM が起動していることを確認
# virsh list
 Id   Name     State
------------------------
 4    mgmt     running
 8    target   running


VirtualBMC をセットアップ

(1) pip をあらかじめ最新化
# pip3 install --upgrade pip

.... 省略 ...

(2) VirtualBMC をインストール
# pip3 install virtualbmc

... 省略 ...

(3) VirtualBMC を起動
# vbmcd


(4) mgmt 用の VirtualBMC を作成
# vbmc add mgmt --port 6230 --username admin --password password


(5) target 用の VirtualBMC を作成
# vbmc add target --port 6231 --username admin --password password


(6) mgmt 用の VirtualBMC を起動
# vbmc start mgmt


(7) target 用の VirtualBMC を起動
# vbmc start target


(8) VirtualBMC 用の Firewall 設定を追加
# firewall-cmd --zone libvirt --add-port 6230-6231/udp --permanent


(9) firewall ルールを再読み込み
# firewall-cmd --reload


mgmt VM 内で NIC, repository 等を設定および ipmitool をインストール

(1) mgmt VM へ root ユーザでログイン
# virsh console mgmt
Connected to domain mgmt
Escape character is ^]

Red Hat Enterprise Linux 8.4 (Ootpa)
Kernel 4.18.0-305.el8.x86_64 on an x86_64

Activate the web console with: systemctl enable --now cockpit.socket

localhost login: 


(2) "Wired connection 1" のインターフェース設定を eth0 用に変更
# nmcli connection modify "Wired connection 1" connection.id "eth0"


(3) eth0 に割り当てる IP アドレス、DNS、デフォルトゲートウェイ等を設定
# nmcli connection modify eth0 connection.interface-name eth0 ipv4.method manual ipv4.address 192.168.24.101 ipv4.dns 192.168.24.1  ipv4.gateway 192.168.24.1


(4) connection を起動し eth0 に設定を反映
# nmcli connection up eth0
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/16)


(5) eth0 の状態を確認
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:8d:7d:30 brd ff:ff:ff:ff:ff:ff
    inet 192.168.24.101/32 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::e11c:7457:cdff:2307/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever


(6) システムの登録情報を初期化
# subscription-manager clean
All local data removed

WARNING

The yum/dnf plugins: /etc/dnf/plugins/subscription-manager.conf, /etc/dnf/plugins/product-id.conf were automatically enabled for the benefit of Red Hat Subscription Management. If not desired, use "subscription-manager config --rhsm.auto_enable_yum_plugins=0" to block this behavior.



(7) システムを登録
# subscription-manager register
Registering to: subscription.rhsm.redhat.com:443/subscription
Username: 
Password: 


(8) 有効な Pool をアタッチ
# subscription-manager attach --pool=<pool-id>
Successfully attached a subscription for: <pool-name>


(9) 使用するパッケージのリリースを 8.4 に固定
# subscription-manager release --set=8.4


(10) すべてのリポジトリを無効化
# subscription-manager repos --disable=*

... 省略 ... 


(11) 使用する2つのリポジトリを有効化
# subscription-manager repos --enable=rhel-8-for-x86_64-baseos-eus-rpms --enable=rhel-8-for-x86_64-appstream-eus-rpms
Repository 'rhel-8-for-x86_64-baseos-eus-rpms' is enabled for this system.
Repository 'rhel-8-for-x86_64-appstream-eus-rpms' is enabled for this system.


(12) パッケージを最新化
# dnf update -y

... 省略 ... 


(13) ipmitool をインストール
# dnf install -y ipmitool

... 省略 ... 

ipmitool で target VM を監視/操作できることを確認

(1) target VM が電源が起動状態であることを確認
# ipmitool -I lanplus -H 192.168.24.1 -p 6231 -U admin -P password power status
Chassis Power is on


(2) target VM の電源を停止
# ipmitool -I lanplus -H 192.168.24.1 -p 6231 -U admin -P password power off
Chassis Power Control: Down/Off


(3) このときの VM の状態をハイパーバイザ側で確認
# virsh list --all
 Id   Name     State
-------------------------
 4    mgmt     running
 -    target   shut off


(4) もう一度 mgmt VM から target VM を起動
# ipmitool -I lanplus -H 192.168.24.1 -p 6231 -U admin -P password power on
Chassis Power Control: Up/On


(5) 再度 target VM が起動状態となっていることをハイパーバイザ側で確認
# virsh list
 Id   Name     State
------------------------
 4    mgmt     running
 9    target   running


まとめ

ハイパーバイザ上で VM をベアメタルサーバかのように操作することができるようになるツール、 VirtulBMC を紹介しました。

レイヤーが高いんだか低いんだかよくわからない記事になりましたが、少しでも誰かの役に立っていれば幸いです。

また、クラウドが主流の時代において物理的なサーバを意識する回数は格段に減少しているかと思いますが、この記事をきっかけに興味をもって頂けた方がおられましたら、ぜひ遊んでみてください。

Ghostscript(PostScript)でフォントデザイン

イントロ

今回は呉高専エンジニア勉強会 Advent Calendar 2017の4日目の記事です。呉高専OBで信州大学B3のNonKuRuです。というわけでアドベントカレンダーに参加することになったので、急遽何か良い題材はないかなと考えたところ思いつかなかったのでGhostscript(PostScript)という言語でフォントデザインをしてみることにした。

Ghostscript(PostScript)とは

そもそもPostScriptに馴染みのない人や初めて聞いたという人も多いと思うので、少し説明する。PostScriptは、画像編集ソフトのPhotoshopIllustrator、動画編集ソフトのPremiere ProやAfter Effectなどで有名なAdobe社によって開発されたページ記述言語のひとつである。

印刷するページ内の文字や画像のようなデータの位置、サイズ、色などをプログラム言語として記述できる。この記述されたスクリプトファイルとPostScriptに対応するソフトウェアとプリンタを使用すれば同じ印刷結果を得ることができる。そのためドキュメントが正確にプリントされることにシビアであるDTPの分野ではグローバルスタンダードとなっている。

コンピュータ黎明期はPostScriptで記述した図形をプリンタで実際に紙に印刷して確認していたが、それをモニタ上でも確認したいということでPostScriptのコードをグラフィックとして表示してくれるIllustratorが開発された。同様にAdobe社が開発したPDF(Portable Document Format)は、PostScriptをベースにして透明やレイヤといった概念も加えた新しいドキュメントフォーマットである。

そしてそのPostScriptをフリーソフトウェアとしたものがGhostscriptである。このGhostscriptは科学研究分野で論文記述のための組版システムとしてよく使用されているTEX(テフ)でもPDFへの変換ソフトとして使用されている。そのためTEXもしくはLATEXがインストールされた環境ではGhostscriptが使える状態になっていると思われる。

簡単な例

実際にどのように記述していくか見ていこうと思う。

・簡単な計算(1)
1 + 3 =これをGS(Ghostscript)で計算するには1 3 add ==と記述する。

・簡単な計算(2)
1 + 3 - 2 =これをGSでは1 3 add 2 sub ==と記述する。

この2つの例からわかるように、GSはスタック指向型の言語である。つまり「add」や「sub」や「==」のようなオペレータが記述されるまで数値は順にスタックにプッシュされ、オペレータが記述された時点までの値と命令の内容によって計算し、その解をこれまた一旦保持し最終的に「==」で計算結果が出力される。ただしオペレータの前に3つ以上数値がプッシュされた状態では最後にプッシュされた2つまでしか計算されずそれ以前にプッシュされた数値はスタックに保持されたままになる。

つまり、1 2 3 add ==の出力結果は 「5」になる。全て加算したい場合は1 2 add 3 add ==もしくは1 2 3 add add ==となる。

以上のことがわかった上で、実際に図形を描画していく。

・直線の描画(相対位置の指定:rmoveto, rlineto)
f:id:n0x2ca:20171203013603p:plain

newpath  
100 200 moveto  
100 100 rmoveto //カレントポイント(描画開始位置を移動)  
200 300 lineto  
250 400 rlineto   //直線描画  
stroke  
showpage  

・直線の描画(幅と色の指定:setlinewidth, setrgbcolor)
f:id:n0x2ca:20171203012604p:plain

newpath  
100 100 moveto  
70 setlinewidth                        //線幅の指定  
100 100 rlineto  
1 0.5 0.3 setrgbcolor stroke   //RGB色の指定  
stroke  
showpage  

・円弧の描画(中心を指定する方法:arc, arcn)
cx cy radius ang_begin ang_end arc //中心 半径 開始角度 終了角度

・円弧の描画(接線を指定する方法:arcto)
px1 py1 px2 py2 radius arcto //2つの接戦を表すための3点と半径を指定

ベジェ曲線の描画(4点の制御点による曲線の描画:curveto)
px1 py1 px2 py2 px3 py3 curveto

・パスを塗りつぶす(fill)
f:id:n0x2ca:20171203014755p:plain

newpath  
140 300 moveto  
100 400 350 400 250 300 curveto  
20 setlinewidth  
0.6 1 0.6 setrgbcolor  
fill  
showpage  

・参考

算術オペレータ 意味 スタックオペレータ 意味
A B add 加算 clear 削除
A B sub 減算 pop ポップ
A B mul 乗算 exch 1番目と2番目を交換
A B div 除算
A B idiv
A B mod 剰余
A B neg 符号反転

オリジナルフォント

今回は「1018」をオリジナルフォントで表現してみた。このフォントのコンセプトは「実用性は完全無視で認知できる最小限の筆の軌跡」である。以下にそれぞれのソースコードも載せておく。
f:id:n0x2ca:20171203021740p:plain

「1」のソースコード

newpath
250 100 moveto
10 setlinewidth
350 100 lineto
300 400 moveto
300 500 lineto
250 450 lineto
0 0 0 setrgbcolor
stroke
showpage

「0」のソースコード

newpath
300 100 moveto
10 setlinewidth
400 100 450 150 450 300 curveto
300 600 moveto
200 600 150 550 150 400 curveto
0 0 0 setrgbcolor
stroke
showpage

「8」のソースコード

newpath
10 setlinewidth
300 200 150 130 320 arc
stroke
newpath
300 500 150 300 150 arc
0 0 0 setrgbcolor
stroke
newpath
250 420 moveto
350 250 lineto
stroke
showpage

アウトロ

今回はプログラミングでフォントデザインをしてみたが、これは実用的かと問われるとその道を極めたい人以外はあまりないと思うので、テクニカルな遊びとして楽しんでもらえると良いのではないかと思う。

VPSでハニーポット運用はセーフなのか

前々からハニーポットを運用してみたいと思っていたが、金銭的に難しくなかなか機会がなかった。しかし、今回さくらインターネットのクーポン券が手に入ったのでこれを機にはじめよう!...と思った。しかしVPSハニーポット運用は契約的にセーフなのか気になったので調べてみた。(これは個人的な見解なので鵜呑みにしないようにお願いします。)

サービスと規約一覧

>犯罪行為、犯罪行為をそそのかしたり容易にさせる行為、またはそれらのおそれのある行為
→場合によってはアウト?
>当社あるいは第三者の運用するコンピュータ、電気通信設備等に不正にアクセスする行為、クラッキング行為、アタック行為、および当社あるいは第三者の運用するコンピュータ、電気通信設備等に支障を与える方法あるいは態様において本サービスを利用する行為、およびそれらの行為を促進する情報掲載等の行為、あるいはそれに類似する行為
→ビミョーww

まとめ

 結果的にハニーポットを明示的に禁止しているところはなさそう?ただ、運用のミスがありサービスに影響を与えてしまった場合はアウトになりそうなところもあったように思える。(無難にラズパイとかで運用したほうがいいのかな〜)  知見のある方からコメントをいただいたところによると、インバウンド(自鯖にアクセスしてくる悪意のある通信)はセーフだけど、アウトバウンド(自鯖から出て行く悪意のある通信)はアウトみたいです。それと、ハニーポットが見破られて破壊されてももちろんアウト!!  ということなので、運用には十分気をつけましょう。

もしこういう場合はアウトといった情報や経験があればコメントをお願いします。m( )m

セキュリティ・キャンプ全国大会2016に参加した

8/9〜8/13に開催されたセキュリティ・キャンプ全国大会2016に参加してきました。このセキュリティ・キャンプはこれまでに13回開催され約600名もの卒業生を輩出しています。その卒業生の方々は様々な分野で活躍されておられ、私としましては憧れの存在です。そんな先輩方に追いつくべく、耳の穴かっぽじって講義を受けてきました!笑

f:id:n0x2ca:20160815234211j:plain

0日目

私は地方から参戦しましたので、初日の集合時間に間に合わないということで会場兼宿泊施設であるクロスウェーブ幕張に前泊しました。私以外にも数人前泊対象の参加者がおられましたので、一足先に名刺交換させていただきました!この日は明日の準備だけして早めに寝ました。

1日目

 いよいよセキュリティ・キャンプが始まりました!会場へ向かうとさっそく本格的なカメラを向けられ抱負を聞かれました。(テンパって噛みまくったww)既に名刺交換の応酬が始まっていたので 「出遅れた」と思いつつも開講式の時間までひたすら名刺交換していました。(同時に数十人が名刺交換していたので誰と交換したかわからなくなりましたw)
 開講式が終わるとセキュリティ基礎講座や特別講義が行われ、大変興味深いお話を聞くことができました!特に特別講義でのインターポールの福森さんのお話はインターポールという組織の重要性やこれまで自分の中になかった視点の話が聞けてとても面白かったです。講義の後に福森さんと名刺交換させていただき、CDIシャツをいただけることに!!(やったぜ!)
 夕食後は会場に戻りグループワークの説明を受けました。テーマは4つあってその中から私たちのグループは唯一「10年後のIT社会のセキュリティのあるべき姿」を選びました。ちなみにチーム名は『osx』(おーえすえっくす)です。(たまたまグループ全員がMacという奇跡w)読みが「おーえすてん」ではないのはあえて。

2日目

 この日から毎朝8:30に専門講義が始まりました。私が受けた講義は「1-C 公開鍵暗号のハードウェア実装と攻撃〜ICカードが持つ脆弱性とその対策〜」と「2-C 人工知能とセキュリティ」でした。専門講義の後はグループ対抗seccamp CTFが開催されました!!
 1-Cではまず公開鍵暗号の概説があり、そのあと実際に機器を使用してICカードに対してサイドチャネル攻撃をしかけ鍵を取り出すということをしました。これは実際のクレジットカードにも有効だということでなかなか中二心をくすぐられる講義でしたw
 2-CではRやPythonディープラーニングを使ってみるという実習と人工知能を活用していく上での問題点として学習の時点でコンタミがある場合の対策などについてグループでディスカッションしました。

3日目

 この日受けた講義は「3-D The OOM CTF」「4-D 実行ファイルの防御機構を突破せよ」「5-A サーバ運用におけるパスワード管理」盛りだくさんな専門講義の後は特別講義として伊藤忠テクノソリューションの方から普段の仕事のお話をしていただきました。
 3-DではLinuxのメモリ管理機構として備わっているOOM killerについてお話していただきました。序盤はふむふむと余裕ブッこいて聞いていたのですが、OOMの本題に入ったあたりからとても難解になりよくわかりませんでしたw(チューターの方にとっても難しかったらしい) さすがLinuxのメモリ管理の闇というだけあるなと感じました。ただ、Linuxカーネルの闇を理解したいという気持ちが湧いてきたのでよかったと思います。
 4-Dでは事前課題で解いたx86バイナリをさらにグレードアップさせた問題をひたすら解析しました。x86バイナリを読むのはだいぶ慣れてきたのですが、ASLRが有効の状態でシェルを奪取するというのは自分には少し難しかったです…。ただGOT領域のアドレスをリークさせるところまではできたので復習して解けるようにしたいと思います。
 5-Aでは業務でペネトレーションテストをされておられる講師の経験をお話しいただいた上で、パスワードの管理方法についてグループでディスカッションしました。以前からパスワードの管理は煩わしいと思っていて何か有効な解決策はないのかと気になっていたので、いろんな意見が聞くことができとても参考になりました。

4日目

 この日受けた講義は「6・7-E インフラセキュリティ・ブートキャンプ」でした。この後に特別講義でDeNAがスタートアップだった頃からインフラを担当されている方になぜセキュリティの仕事をしているのかというルーツをお話をしていただきました。
 6・7-Eでは主にAWSをterraformというツールを使いチームで構築するというものでした。私はAWSもterraformも今回初めて触ったので、AWSの環境と構築方法の理解とterraformとの関係性などについて調べるとこから始めました。その後手動でAWSと構築し、ある程度理解した後terraformを使ってVPCを構築してみるとその容易さわかりやすさに驚きました。これを機にクラウドでのインフラ構築もやっていきたい。

5日目

 最終日は午前中にグループワークの発表がありました。他のグループはとても面白い発表していてやべーってなってましたw
発表終了後は昼食食べて閉講式して集合写真撮ってという感じでした。集合写真のとき今年のセキュキャンのキーワードでもある「今日も1日がんばるぞい!」を何回言ったかわからないw そして最後になんと!!プレゼントタイム&サイン会!!!様々な技術本や雑誌、Tシャツ、グッズなどをいただきました!(圧倒的感謝!!!!!!)

f:id:n0x2ca:20160815234255j:plainf:id:n0x2ca:20160815234310j:plainf:id:n0x2ca:20160815234317j:plainf:id:n0x2ca:20160815234323j:plain

感想

 参加する前は4泊5日は長いな〜と思っていましたが、終わってみるとまだまだやりたいという思いでいっぱいでした。CTFは時間が短かったのでここからというところで終わってしまいちょっと残念でした。
 私はあまりアニメを見ないのでついていけてないところもあり、会話に入れないことがあったので今後はアニメトラックもがんばりますww そして来年はチューターとして参加したいと思います!!

さいごに

 今回セキュキャンに参加させていただくことで各技術分野のトップの方たちとお話ができたり、SNSで繋がれたり、ともに頑張る仲間できたりと技術や知識以上に得られるものが大きかったです。技術力をあげたいという人や仲間がほしいという人は絶対に参加すべきだと思います。ただセキュキャンに参加することがすべてではないですし、参加して満足するようでは意味がないのでそこをお忘れなきを。

Bluelog README 和訳

気が向いたのでBluelogという近くにあるBluetoothバイスを検知するツールのREADMEを和訳してみた。英語の勉強という面もあるので、訳が間違ってたり表現がよくないところは優しく指摘していただければとても喜びます。

原文 GitHub - MS3FGX/Bluelog: A highly configurable Linux Bluetooth scanner with optional web interface.

Bluelog

Bluelogはwebサイトでの調査やトラフィック監視用に設計され、システムのデーモンかwebフロントエンドを選択して実行させることができるLinuxBluetoothスキャナーである。それは長期間、特定の静的な場所でその範囲にあるできるだけたくさんのBluetoothバイスを発見できることも目標としている。

Bluelogは放置されるように設計されているので、ユーザーインターフェースを持っていないし、一度スタートさせると何の操作も必要はない。その特色としては完全にログファイルのフォーマットが設定可能であり、同様にsyslogへネットワークを超えた中央集積型のログの機能がある。

Bluelogは貧弱で小型であるx86MIPS、ARMプロセッサで動作するよう設計された。BluelogはKali linux(www.kali.org)やPwnie Express(www.pwnieexpress.com)が提供しているPwn Pad やPwn Plugペネトレーションテストバイスに含まれている。また公式のOpenWRTレポジトリーやArch Linux AUR コミュニティーレポジトリからも入手可能である。

Bluelog Live

Bluelog Liveは定期的に発見されたデバイスの更新を提供し、それらの該当する情報は任意のwebブラウザから見ることができる。Liveモードは主に公開情報や、悪名高い”Wall of Sheep”からインスピレーションを受け設計された。(www.wallofsheep.com)

高度なLiveモードはメインのBluelogツールから分割されたソフトウェアであある。それはシンプルな静的なHTMLページやCGIモジュールから構成されBluelogからのログファイルを読み込む。

Bluelogはwebサーバではなく、ただ単にあなたが選択したHTTPデーモン(Apachelighttpd、etc)が提供するHTMLファイルを生成する。したがって、Bluelog Liveをスタートさせてみる前にwebサーバはすでに適切に設定されているか確認がいる。Bluelogは実は起動中Liveページの状態に全く気づかない。それはまさに吐き出すデータがベストな状態であることを望んでいる。

Basic Option

-i
このオプションはBluelogにあなたがスキャンしたいBluetoothバイスを伝える。あなたはHCIデバイス名(hci2のような)かローカルアダプタのMACアドレスを使うことができる。ボーナスとして、もしあなたが存在しないデバイスを与えるなら、Bluelogは稼働しているデバイスを自動検知し戻ってくるだろう。
-o
これはログを書き込むファイルを任意のファイル名にできる。デフォルトのフォーマットは”bluelog-YYYY-MM-DD-HHMM.log”で、カレントディレクトリに作られる。 -v
このオプションを付加すると見つかったデバイスをコンソールに表示する。出力にはくどくどとデバイスクラスの情報やタイムスタンプの記録が含まれている。デフォルトではこのオプションはOFFになっている。
-q
これは重要ではない出力をOFFにする。これが意味するのは、通常ではスキャンの実行開始時間と適切なシャットダウンがされたかのメッセージしか見ることができない。
-d
このオプションはBluelogをバックグラウンドで動作するデーモンとして起動する。まだ定型文やスタートアップメッセージを見ることになるだろう、しかしその後はターミナル内でBluelogから情報は少しも見かけないだろう。
-k
Bluelogプロセスがデーモンモードで実行されているときに、-kオプションはそのプロセスを停止することができる。

Logging Option

-n
このオプションを使うと発見されたデバイスのデバイス名が表示される。デバイス名を見つけることに時間がかかりすぎ時折失敗することがある。したがってデバイス名を解決しないことにより、Bluelogは高速にそして正確にスキャンできる。デフォルトではOFFになっている。
-m
このオプションを利用可能ならMAC OUIを通して稼働しているハードウェアメーカーを特定する。ハードウェアメーカーはBluelog Liveと同様に標準のログファイルに記録されているだろう。この機能を利用するにはいくつかのプラットフォーム(OpenWRTのような)メーカーの法外に大きなデータベースをインストールする必要がある。
-c
このオプションを指定すると生のデバイスクラスをログファイルに書き込むようになる。このオプションをOFFにするには -f を使う。デフォルトではOFFになっている。
-f
このオプションはデバイスクラスを翻訳し多くの人が読みやすい形式にする。それはデバイスのクラスとコア容量を教えてくれるだろう。例えば、クラス”0x7a020c”は”Smart Phone, (Net Capture Obex Audio Phone)”として見える。このオプションをOFFにするには -c を使う。デフォルトではOFFになっている。
-t
このオプションを使うとスキャン開始時間と終了時間、また新しいデバイスが発見された時間がログファイルに記録されるようになる。デフォルトでは OFFになっている。
-x
このオプションを使うとMACアドレスをうやむやにすることができる。このオプションをONにすると、Bluelogは発見されたそれぞれのメーカー部分のMACアドレスを表示するが、デバイスを固有の情報はブロックする。デフォルトではOFFになっている。
-e
このオプションを使うとMACアドレスをCRC32形式へエンコーディングする。このオプションをONにすると、発見されたこれまでディスクに記録されていないMACアドレスはこの形式で記録される。 -a
このオプションは”amnesia mode”を可能にすると与えられた時間が経つとBluelogは一度発見した特定のデバイスを忘れてしまう。このオプションによってBluelogはデバイスと出会ったとき、初めて出会ったものとして再びログに記録し、発見された時間も更新されるだろう。

Output Options

-l
このオプションはBluelogを中継してLiveモードも変更する。コンソールやログファイルよりも自動的に更新されるwebページの結果を表示する。
-b
このオプションは結果のデータがronin’s Bluetoothプロファイリングプロジェクト(BlueProPro)へのアップロードにふさわしいログの形式に設定する。これは他の多くのログオプションを上書きし、Bluelog LiveはOFFになる。このプロジェクトのさらなる情報と、さらなるヒントはあなたのデータを提出してもらう必要がある。www.hackfromacave.com
-s
このオプションを使うとsyslogのみに出力するモードになる。このモードではBluelogは通常のログファイルには記録しない代わりにシステムログファイル(/var/log/syslog)だけに記録される。このモードはネットワークで接続されたsyslogデーモンに気づかない時に特に便利であり、複数のBluelogにより記録されたログを一箇所に集約する際にも使うことができる。

Acknowledgemets

Bluelogの開発当初はAlbert Huangによって執筆された”Bluetooth Essentials for Programmers”という本に含まれているサンプルコードをもとに製作されていました。この本はとても有益な本であり、もしあなたがBlueZプログラミングの入門書を探しているのならとても役立つだろう。それはBlueZプロジェクトのひどいドキュメントを ほとんど補完してくれるだろう。

この本に関するwebサイト:http://www.btessentials.com/

Bluelogのデバイスクラスを解析するコードはMichael John Wensleyによって執筆されGPLv2によって保障されている”Inquisition”を実装している。

“Inquisition"に関するさらなる情報を読みたいのなら彼のサイトへ:http://www.wensley.org.uk/

BluelogはSven Reifegersteによってかかれた”CRC Tester”のCRCハッシュ関数の修正バージョンを実装している。

CRCエンコーディングに関するSvenのページ:http://www.zorc.breitbandkatze.de/crc.html

.roninによる”SpoofTooph”はリテラルコードではないデバイスキャッシュの書き換えという素晴らしい発想をくれた。”SpoofTooph”と.roninの他のプロジェクトは彼のサイトからチェックすることができる:http://www.hackfromacave.com/

BluelogのUDP関数はlan Macdonaldが提出したコードをもとにされている。(ianmac51@googlemail.com)

BluelogもまたMartin Schlzeによってかかれたpidfile.cに含まれる関数にインスパイアされたコードをいくつか使用している。

Bluelog Liveのロゴに使用されているフォントはJakob Fischerによる”Electric Boots”である。彼のフォントコレクションはここでみることができる:http://www.pizzadude.dk/

BluelogのOpenWRTバージョンはGary Bonnerの仕事ぶりやJoshua HurstとDean Nielsonの陰の支えがなければ可能ではなかっただろう。Stephen Walkerもありがとう。彼女はBluelogのためにプラットフォームの貴重な情報である公式のOpenWRTパッケージを保守し続けてくれた

BluelogのためにArch Linuxの組み込みスクリプトを保守してくれてありがとう、Jonas ”onny” Heinrich。彼のプロジェクト:http://www.project-insanity.org/

BluelogようにカスマイズされたPwn Plug上での支援や助力には大変感謝します、Dave Porcello、Jonathan Cran、Punie Express team。

イタリアのボルザノでネットワークトラフィックモニタリングの構造を開発している間にBluelogへパッチを当ててくれた、Paolo ValleriやIntegreenプロジェクトありがとう。プロジェクトサイト:http://www.integreen-life.bz.it/

DEFCON Privacy VillageのテーマにBluelog Liveを組み入れてくれたTeresa Brooksありがとう。

Bluelogについてのコメントや提案をしてくださり正しい方向へと私を進めてくださったすべてのユーザに感謝します。

最後に、調整の目的で私にBluetoothバイスを寄付してくださった方々に感謝いたします。スキャンするデバイスがなしでBluetoothスキャナーをかくことはかなり難しい、そのためハードウェアは私にとって大変貴重である。

License

このプログラムはフリーソフトウェア;あなたはフリーソフトウェア団体によって公開されているGNU GPLv2のライセンスによりこれを再配布または修正して再配布ができる。
このプログラムは便利になるよう望まれて配布されている。しかしなにも保証はない。;暗にほのめかされる市場的な保証や特定の適性な目的のようなものもない。
詳細はソースディレクトリに含まれている”COPYING”ファイルを見て。

C言語の参照外しとダブルポインタ

ふと、「参照外し」の語源というか由来というかそんなものは何かあるのかな〜と思いググってたところ別のある問題に出くわした。 これってみんなパッと答えられるのかなと思い書いてみた。 そのソースコードが以下である。

gistd9a5cbadb0c86a3adb99cb94b95302a5

問題はこれの出力を答えろというもの。

char型の配列とポインタ変数が宣言してある。 そして、ポインタ変数に配列のアドレスが代入され、出力してある。 という簡単なC言語のプログラムである。 慣れてる人ならこんな問題は瞬殺なんだろうけど、自分は少し考えてしまった... ということで、整理も兼ねて解答を書いていく。

解答

まず1つ目の出力から。
char mark_1[][5] = {"zyx", "wv", "utsr", "qpo", "nmlk"};
まずこれは普通にchar型の二次元配列を宣言して初期化しているだけ。
printf("%s¥n", mark_1[1] + 1);
出力ではフォーマットパラメータに%sが指定されている。(文字列を出力) その出力の値としてmark_1[1] + 1が指定されている。
これはまずmark_1[1]で配列の要素"wv"のアドレスを指定し、そのあと"wv"要素の中の先頭から+1個進んだ先の文字列"v"が出力される。

2つ目の出力
printf("%s¥n", pt_1 + 1);
これも1つ目と同様の考え方で理解できる。ただ、今度はmark_1を直接使っているのではなくpt_1にmark_1のアドレスを代入してそれを利用している。この場合pt_1ではすでに*mark_1が代入されているので、配列mark_1の先頭要素であることが確定している。(1つ目と表記をあわせるならpt_1=*mark_1=mark_1[0])そして要素内で+1してあるので、結果出力は"yx"になる。

3つ目
ここはもう1つの配列
char *mark_2[5] = {"cba", "ed", "ihgf", "lkj", "ponm"};
を使っている。そして
pt_2 = mark_2;
で配列mark_2の先頭アドレスをpt_2に代入。
printf("%s¥n", *pt_2 + 2);
ここでは*pt_2で先頭の要素"cba"を指しており、+2で先頭から2つ進んだ先の"a"を出力している。

4つ目
printf("%c¥n", **pt_2 + 2);
ここがちょっと特殊である。といっても難しくはない。フォーマットパラメータは%cとなっている。(1文字を出力)そしてその値として**pt_2+2となっている。この考え方としては、参照外しの演算子「*」と四則演算子では参照外しの演算子が優先されるということと、値として特定の文字が確定したあとに四則演算を用いるとASCIIコードの計算とされることだ。具体的に言うと、まず**pt_2で配列mark_2の先頭要素の先頭文字"c"が確定する。この時点で+2はポインタ演算ではなくなりASCIIコードでの+2となる。そのため"c"の2つ先のアルファベット"e"が出力されることになる。間違っても配列の要素の"ed"の"e"が出力されたわけではない!

5つ目
printf("%s¥n", *(pt_2 + 2) + 2);
pt_2+2してから参照外しをしているので配列要素の"ihgf"を指しており、その後さらに+2しているので"gf"が出力される。

これで終わり。

まとめ

参照外しや[]の優先度はあまり気にしたことがなかったので以下のサイトで確認してみた。

C Operator Precedence - cppreference.com

すると、やはり優先度はa[ ] > *a となっている。そして四則演算子よりも参照外しの方が優先度が高いことがわかる。
言われてみれば当たり前な話だけど、演算子の優先度に気をつけよう。そしてなにより基本は大事!

バイナリ解析環境構築メモ

Virtual Boxを使用し、仮想環境でUbuntuを起動できる状態を前提とします。

構築環境

  • Ubuntu 16.04 LTS
  • Virtual Box VM version 5.0.22

入れていくもの

  • Linuxコマンド
    • file
    • readelf
    • strings
    • grep
    • unzip/tar/gzip/xz
  • トレーサ
    • strace
    • ltrace
  • デバッガ
  • アセンブラ
    • objdump
  • その他
    • radare2
    • rp++
    • checksec.sh
    • peda
    • socat
    • pwntools

構築開始

Linuxコマンド

各種コマンドがあるか確認(Ubuntu16.04の場合上記コマンドは全て入っていた)

トレーサ

各種コマンドがあるか確認(Ubuntu16.04の場合上記コマンドは2つとも入っていた)

デバッガ

$sudo apt-get install buld-essential gcc-multilib git gdb

アセンブラ

$sudo apt-get install binutils

その他

radare2

$sudo apt-get install radare2

rp++

$mkdir $HOME/bin
$wget https://github.com/downloads/0vercl0k/rp/rp-lin-x64 -O $HOME/bin/rp

checksec.sh

$cd ~/Download/
$wget https://github.com/slimm609/checksec.sh/archive/1.6.tar.gz
$tar zxvf 1.6.tar.gz
$cp checksec.sh-1.6/checksec $HOME/bin/checksec.sh

peda

$sudo apt-get install build-essential gcc-multilib
$git clone https://github.com/zachriggle/peda.git ~/Download/peda
$echo "source ~/Download/peda/peda.py" >> ~/.gdbinit
$export PATH=$PATH/bin:$PATH

socat

$sudo apt-get install socat

pwntools

$sudo apt-get install python-pip python2.7-dev openssl libssl-dev libbz2-dev libreadline-dev libsqlite3-dev
$sudo pip install --upgrade pip
$sudo pip install pwntools
もしここで
Failed building wheel for cryptography
Failed building wheel for cffi
のようなエラーが出る場合
$sudo apt-get install libffi-dev
$sudo pip install cryptography

まとめ

まだ必要なツールはあると思うが、とりあえずここまで。いろいろ試しながらだったためミスがあると思う。(メモしとけばよかった...)