Flisan's Personal Blog

← 記事一覧へ


学習記録

QEMU で多機能 IC カードリーダを Passthrough する

AI researched for this この記事を書くにあたって、AI に調査してもらいました

確定申告お疲れ様でした。

freee の “自動で経理” の未処理帳簿数が 200 とか行ってて横転しそうになりましたが、X で 2,000 件を超える帳簿が未処理になっているという大横転の光景を目にし、やっぱりそうなるんだなあという気持ちとそこまで行くんだなあの気持ちになりました。

ところで、私は普段は MacBook Air …… から Arch Linux が動いているデスクトップ PC にSSH をして作業をしているのですが、今回のように Windows を使いたい場面もあるので、Arch Linux 上で QEMU を動かして、Windows も使えるようにしています。三刀流です!

そして、Windows 上で e-Tax を使うために、IC カードリーダ経由でマイナンバーカードの読み取りが必要だったのですが、QEMU 上で動いているのでただ USB ケーブルを指すだけではQEMU 上で使えるようになりません。デバイスを Passthrough するのは簡単なので、大きな問題ではないのですが、私が使っていた IC カードリーダは SD カードとかも読める多機能なタイプで、デバイスをそのまんま Passthrough すると USB Composite Device とだけ認識されて具体的なインターフェースは使えないという自体に陥りました。

この記事はそれを解決するための備忘録です。

解決策: 利用したい Interface を usbredirect でいい感じにする

この世には USB の Interface を TCP で配信するというすごい概念#1 が存在するらしく、QEMU がそれに対応しています。

具体的な手順

  1. usbredirect を落とします。Arch Linux はこのパッケージ名ですが、他の Distribution でもあると思う。というか Arch Linux であれば qemu-full についてくるので、すでに入ってるかも。
pacman -S usbredir
  1. lsusb -t で、リダイレクトしたいやつを見つけます。
$ lsusb -t
/:  Bus 001.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/10p, 480M
    |__ Port 002: Dev 012, If 0, Class=Chip/SmartCard, Driver=[none], 480M
    |__ Port 002: Dev 012, If 1, Class=Mass Storage, Driver=usb-storage, 480M
    |__ Port 009: Dev 006, If 0, Class=Vendor Specific Class, Driver=xpad, 12M
    |__ Port 009: Dev 006, If 1, Class=Vendor Specific Class, Driver=[none], 12M
    |__ Port 009: Dev 006, If 2, Class=Vendor Specific Class, Driver=[none], 12M
    |__ Port 009: Dev 006, If 3, Class=Vendor Specific Class, Driver=[none], 12M
/:  Bus 002.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/4p, 10000M
/:  Bus 003.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/4p, 480M
    |__ Port 004: Dev 002, If 0, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 004: Dev 002, If 1, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 004: Dev 002, If 2, Class=Human Interface Device, Driver=usbhid, 12M
/:  Bus 004.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/4p, 10000M

ここでは、Bus 001 の下の、Dev 012, If 0Class=Chip/SmartCard なので、これが該当します! #2

同じ Device の別 Interface Dev 012, If 1Class=Mass Storage がありますが、この IC カードリーダは SD カードも読めることから辻褄が合います。

  1. QEMU の引数に以下を追加します。
  # Create a USB 3.0 Controller...
  -device qemu-xhci,id=xhci
  # Receive redirection...
  -chardev socket,id=scredir,host=127.0.0.1,port=12345,server=off
  # Connect it to the controller
  -device usb-redir,chardev=scredir,bus=xhci.0

libvirt 等、別の方法で仮想マシンを立てている場合の設定方法は、申し訳ないですがわかりかねます#3、、ChatGPT に聞いたほうがいいかも。

  1. usbredirect を起動します。
    後述しますが、(Dev)1 を指定すると即死攻撃を受けるので本当に気をつけてください……!
$ sudo usbredirect --device "(Bus)-(Dev)-(If).0" --as 127.0.0.1:12345

Port はガン無視です! 例えば、上の例なら 1-12-0.0 が指定結果になります。

最後の .0 は、ChatGPT 曰く bAlternateSetting の値らしい。lsusb -v でそれも含めた細かい値を全部見れるので、「ちゃんと指定してるのに上手くいかないんだけど」という問題が発生したら、bAlternateSetting がワンチャン 0 以外になってるかもしれません。

正しく指定できれば、エラーメッセージも何も出ず、usbredirect がずっとそのターミナルで動き続けるはずです!

  1. 後は QEMU を起動すれば使えるはずです!Windows にログイン後、Windows+X → デバイスマネージャで、スマートカードリーダーが認識されていれば、Windows も JPKI の仲間入りです!