2026/09/28(月)WoL対応のSFP+ 10GbE NICを買ってWoLを実現した

以前買ったMellanox ConnectX-4でWoLができなかった話の続き。

SFP+搭載NICを使い、WindowsマシンをWoLを使ってスマホから起こすのをやる話。

やりたいこと

流れとしてはスマホからUbuntuサーバーにSSHで繋ぎ、UbuntuサーバーからWindowsデスクトップへマジックパケットを送付して起こす。Windowsが起きたらスマホからWindows側にSSH接続して扱う内容。

Cloudflare TunnelやTailscaleは使わずにSSH直結で扱い、スマホ→Ubuntu→Windowsのように踏み台を使うこともしない。

使ったもの

デバイス

Windows~L2スイッチ間で使っているもののみ。

種類 デバイス
マザボ ASRock Z890 Pro RS
NIC TXA403
DACケーブル 10Gtek CAB-10GSFP-P2M-30
スイッチ MikroTik CRS305-1G-4S+IN

ソフトウェア

Env ver
Windows Windows 11 Pro 25H2
Ubuntu Ubuntu 24.04.4 LTS
WoL wakeonlan version 0.41

ネットワーク構成

大まかにこんな感じ。図には書いてないがLAN内にはWiFi APもあり、そこからも叩ける。

やったこと

Windowsデスクトップ側

  1. BIOSでPCIe経由の起動を許可するように設定
  2. Realtek PCIe FE / GbE / 2.5GbE / 5G / 10G Family Controller Softwareから「DASH all-in-one Installer for Win10/Win11」をダウンロードし、インストール
    • ここはNICを挿す前にやっておくといいと思われる
  3. NICを挿す
  4. デバイスマネージャーでWoLが有効になっていることを確認(デフォルトで有効だった)

Ubuntuサーバー側

wakeonlanと言ういかにもそのままなパッケージを入れるだけ。入れたらMACアドレスを指定して叩くとマジックパケットを投げることができる。長いのでエイリアスを貼っておくと楽。

sudo apt install wakeonlan
wakeonlan <MACアドレス>

Android側

適当なSSHクライアントでUbuntuに繋ぎ、wakeonlan <MACアドレス>を流し、Windowsを起動させる。

開封の儀とか紆余曲折の話

SKN-8127AF-X1ではダメだった話

以前買ったMellanox ConnectX-4でWoLができなかった話ではSKN-8127AF-X1を使うことを検討していたが、DACとの相性が悪いのかこれは使えなかった。まずDACケーブルを挿してもLEDが付かず、OSから見ても当然線が刺さってない扱いだった。

SKN-8127AF-X1自体は日本語の取説まであり、いい感じのパッケージだっただけに残念だ。

しむふり生活というブログによるとオートネゴシエーションの設定が死んでいるので、手動でリンク速度を設定すれば行けるらしいが、この情報を知る前に処分したためもう分からない。

ブラケットもやたら傷まみれだったし、単純に不良品だった可能性もあるが今となっては解らない。

コネクタはPCIe4.0x1で、空きがあればどこにでも挿せるのは嬉しかった。

TXA403開封の儀とか

TXA403が届くと箱にRJ45が描かれており、封印もセロテープだったため、一抹の不安に襲われた。

しかし開けてみるとちゃんとSFP+だった。手抜きか?

SKN-8127AF-X1と比べると内容は随分簡素で、個別の袋やネジ、取説はなかったが、あっちが無駄に豪華すぎるだけで別にこれでいい気がした。

ヒートシンクをSKN-8127AF-X1と比較すると目が少なく、向きも違うので若干冷却性能は下がるかもしれないが、恐らく問題になることはないだろう。

コネクタはPCIe3.0x4で、PCIe4.0x1だったSKN-8127AF-X1と比べると大きかった。

ブラケットもピカピカで問題なかった。

取付時に思ったこととして、ゲーミングPCはよく光るため、この程度のパーツの取り付けなら懐中電灯が要らなくて便利だなと思った。

以前使っていたHuawei STL2IEA2Aと比べるとだいぶ小さい。基板が青色なのも少し珍しい気がした。

Huawei STL2IEA2Aとの比較

TXA403側は情報が少ないので一部の情報はググって出てきたのを適当につぎはぎしている。

機能 Huawei STL2IEA2A TXA403
チップセット Mellanox ConnectX-4 Lx Realtek RTL8127ATF
消費電力 12W 1W
コネクタ PCIe3.0x8 PCIe3.0x4
ポート数 2 1
WoL 非対応 対応
Linux対応 ◎ △
Windows対応 ◎ ◎

RTL8127ATFはLinux対応がイマイチらしく、UbuntuだとWoLを有効にすると問題が起きるっぽい?ので、Linuxでの使用は微妙かもしれない。

ベンチマーク

WindowsからUbuntuに飛ばす速度については、前回計測時より若干早くなっているように感じた。逆は特に変わらず。

Windows → Ubuntu

[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec  1.11 GBytes  9.52 Gbits/sec
[  5]   1.00-2.01   sec  1.11 GBytes  9.49 Gbits/sec
[  5]   2.01-3.00   sec  1.10 GBytes  9.49 Gbits/sec
[  5]   3.00-4.01   sec  1.12 GBytes  9.49 Gbits/sec
[  5]   4.01-5.00   sec  1.09 GBytes  9.49 Gbits/sec
[  5]   5.00-6.02   sec  1.12 GBytes  9.49 Gbits/sec
[  5]   6.02-7.00   sec  1.09 GBytes  9.49 Gbits/sec
[  5]   7.00-8.01   sec  1.11 GBytes  9.49 Gbits/sec
[  5]   8.01-9.02   sec  1.11 GBytes  9.49 Gbits/sec
[  5]   9.02-10.01  sec  1.10 GBytes  9.49 Gbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-10.01  sec  11.1 GBytes  9.49 Gbits/sec                  sender
[  5]   0.00-10.01  sec  11.1 GBytes  9.49 Gbits/sec                  receiver

Ubuntu → Windows

[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.01   sec  1.09 GBytes  9.26 Gbits/sec
[  5]   1.01-2.00   sec  1.07 GBytes  9.27 Gbits/sec
[  5]   2.00-3.01   sec  1.09 GBytes  9.27 Gbits/sec
[  5]   3.01-4.00   sec  1.07 GBytes  9.28 Gbits/sec
[  5]   4.00-5.01   sec  1.09 GBytes  9.28 Gbits/sec
[  5]   5.01-6.01   sec  1.07 GBytes  9.28 Gbits/sec
[  5]   6.01-7.01   sec  1.09 GBytes  9.29 Gbits/sec
[  5]   7.01-8.00   sec  1.07 GBytes  9.29 Gbits/sec
[  5]   8.00-9.01   sec  1.09 GBytes  9.28 Gbits/sec
[  5]   9.01-10.00  sec  1.07 GBytes  9.28 Gbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-10.00  sec  10.8 GBytes  9.28 Gbits/sec                  receiver

あとがき

R86S U1のNICを交換したのと今回の作業でSFP+対応のNICが2枚も余ってしまった。

まさかこんなニッチなNICを早くも二枚も余らせてしまうとは…。ひとまずは予備に持っているが、どうしたものか。

2026/07/10(金)Windows 11でウィンドウが切り替わりづらい問題を解消したような気がする

投稿日:

Alt+Tabやタスクバーからのマウス操作で上手く切り替わらないことがあったので、その対策。

この問題自体の再現性が低い問題があり、これで完全に解消するかどうかは不明だ。そのため、まだ検証中である。

確認環境

  • Windows 11 Pro 25H2 (OSビルド26200.8737)

前提条件

  • タスクバーを自動で隠す設定にしている
  • タスクバーのボタンをまとめる設定にしている
  • タスクバーのボタンにラベルを出していない
  • タスクバー関係のユーティリティソフトを使っておらず、Windows標準の状態

解決する問題

こういう面倒な状態を解消する。

  • Alt+Tabでウィンドウを切り替えたのに切り替わってない
  • タスクバーからウィンドウをクリックしたのに切り替わらない
  • 前面にあるウィンドウをすべて最小化することでどうにか切り替えている状況

解決した方法

タスクバーを自動で隠す設定をやめるだけで解決した。

推定原因

タスクバーを自動で隠す設定でも切り替わる切り替わらないウィンドウがあるが、恐らくタスクバーを自動で隠す設定で、タスクバーの裏に回っているウィンドウがいるとそこに切り替わりづらくなると思う。

ただ、隠す設定をON/OFFすると、その瞬間は改善し再発しなくなったため、確証はない。

2026/06/27(土)nginxでGeoIP2とUserAgentを利用したアクセス制御を実装してみた

更新日:
投稿日:

過去に何度かBOTなどを避けるためのアクセス制御を導入していたが、結果どれも微妙だった。しかしどうにかしたい、そうだ、nginxは高機能なのでできるんじゃないか?と思って実践してみたログ。

User-AgentはGEOIP2と何も関係ないが、ついでにやったので書いている。

確認環境

Env Ver(apt上) 備考
nginx 1.24.0-2ubuntu7.13 nginx -vではnginx/1.24.0 (Ubuntu)
nginx-common 1.24.0-2ubuntu7.13
libnginx-mod-stream 1.24.0-2ubuntu7.13
libnginx-mod-http-geoip2 1:3.4-5build2

やったこと

互換性確保のためnginxのダウングレード

インストールされていたnginxが1.26.1-2~jammyで、libnginx-mod-http-geoip2との互換性がなかったためダウングレードすることにした。

まず次のコマンドで整合性を確認した。コマンド自体はGPT-5.5が作ってくれたものであるが、こうすることでダウングレードを許可した上での互換性チェックができるようだ。

コマンドの実行結果としては既に追加されているコンポーネント、ダウングレードされるコンポーネント、新たに追加されるコンポーネントの一覧が出てくる。

# ngx_http_geoip2_module.soが存在しないことを確認。既にある場合は本項の工程は飛ばせると思う
ls -la /usr/lib/nginx/modules

sudo apt install -s --allow-downgrades \
  nginx=1.24.0-2ubuntu7.13 \
  nginx-common=1.24.0-2ubuntu7.13 \
  libnginx-mod-stream=1.24.0-2ubuntu7.13 \
  libnginx-mod-http-geoip2

上記の構成でインストールできることが分かったので-sを外してnginx本体をダウングレードし、他をインストールする。

sudo apt install --allow-downgrades \
  nginx=1.24.0-2ubuntu7.13 \
  nginx-common=1.24.0-2ubuntu7.13 \
  libnginx-mod-stream=1.24.0-2ubuntu7.13 \
  libnginx-mod-http-geoip2

# ngx_http_geoip2_module.soが増えていることを確認
ls -la /usr/lib/nginx/modules
ngx_http_geoip2_module.so

GEOIP2データベースの入手と配置

MMDBなら何でも行けると思うので、Matomoで使ってる無料の奴を使う。理想的にはCRONで定期取得するのがいいと思うが、面倒なので今回はやってない。

sudo mkdir -p /usr/share/GeoIP
sudo wget https://download.db-ip.com/free/dbip-country-lite-2026-06.mmdb.gz -O /usr/share/GeoIP/dbip-country-lite.gz
gunzip /usr/share/GeoIP/dbip-country-lite.gz

nginxの設定でGEOIPの有効化を行う

/etc/nginx/nginx.confに以下の設定を追記すると、$geoip2_で始まる変数にMMDBの中身が入るようになる。

load_module modules/ngx_http_geoip2_module.so;

http {
    ...

    geoip2 /usr/share/GeoIP/dbip-country-lite {
      auto_reload 24h;
      $geoip2_metadata_country_build metadata build_epoch;
      $geoip2_country_code country iso_code;
      $geoip2_country_name country names en;
    }

    ...

nginxのJSONログに国コードを含める

JSONログにキーを追加してやればよい。

http {
  ...

  log_format main_json escape=json
  '{'
      ...
      '"country_code":"$geoip2_country_code"'
  '}';

国コードとUserAgentの判定フィルタの元ネタを作る

nginxのmap構文を使って判定用の元ネタを作る。

左側は~で始めると正規表現扱いになり、~*とすると大文字小文字の違いを無視してくれるようになるらしい。

http {
  # headlesschromeを2にしてるのは、これはちょっと毛色が違うと思ったため、便宜上分類分けしている。
  # 但し現時点でこの値を特別扱いしておらず、1と等価なので無駄ではある。
  map $http_user_agent $deny_ua {
    default                 0;
    "~*meta-externalagent"  1;
    "~*baidu"               1;
    "~*headlesschrome"      2;
    ""                      1;
  }

  map $geoip2_country_code $deny_ca {
    default 0;
    "CN"    1;
    "BR"    1;
    "IN"    1;
  }

  # nginxのif文にはandやorに相当する演算子がないのでmapで合成しておく
  map "$deny_ua:$deny_ca" $deny_client {
    default 1;
    "0:0"   0;
  }
  ....
}

雰囲気で読んでいるが構文の意味合いはこうだと思う。KeyValueで並べていくと入力値($input_variable)のKey(input_value)に対するValue(output_value)が出力値($output_variable)に入るのだと思う。

map $input_variable $output_variable {
    default <default_value>; # デフォルト値
    input_value output_value;
    ...
}

フィルタ用のsnippetsを作る

vhostに撒くように/etc/nginx/snippets/deny_client.confのようなsnippetsを作る。

前述のmapで判定をまとめているのでif文一つで制御できるようになっている。

if ($deny_client = 1) {
  return 403;
}

snippetsをvhostに撒く

反映したいvhostの設定にsnippetsを撒いていく。

server {
  ...

  include snippets/deny_client.conf;

  ...

動作検証

こんな感じで検証して弾かれてれることを確認した。国コードはどうにもならないが原理上問題ないはずなので大丈夫だろう。

curl -H "User-Agent:meta-externalagent/1.1" https://lycolia.info

あとは念のために国コードが出ているかどうかをnginxのログを見て出ていたらOK。

関連記事

あとがき

今回のアクセス制御の導入にあたり、運用面で課題のあるAnubisを回避しつつ、大量に存在するCGIにラッパーCGIを嚙ますなどの対応を回避できたのはよかった。

nginxは何とも高性能だ。そして自宅サーバーに全部乗せしたおかげで、レンタルサーバーでは決して手が届かないことができるのが良いと思った。

しかしググってもGEOIP無印の情報ばかりで、GEOIP2の情報が全然なかったので地味にハマってしまった。こういう時LLMに情報を漁ってもらうと取っ掛かりが得られて突破口を見つけられたりするので便利だと感じる。

パッケージを見ていて気になったこと

パッケージを見ていて気になったことは元のコードは保守されてないにもかかわらず、ディストリごとにコードが保守されているように見えたことだ。

今回導入したのはlibnginx-mod-http-geoip2だが、これは元を辿ればDebianのlibnginx-mod-http-geoip2のようで、更に元を辿るとleev/ngx_http_geoip2_module: Nginx GeoIP2 moduleに行きつく。

何故ならDebianのリポジトリがGitHubより新しく、READMEの中身が同じだからだ。設定方法もまるっきり同じに見える。

GitHubのリポジトリは2年以上放置されており「Support nginx 1.23.0」で時が止まっているが、Ubuntuでは「Rebuild against new nginx 1.30.1.」とあるため、だいぶ新しいところまでサポートが進んでいる。

よく考えるとパッケージのバージョンに-ubuntuみたいなのがついているのも良くあることなので、もしかしたらディストリごとにこういったアプリケーションを保守していたりするのだろうか?

そういえばPHPなんかも本家がサポート切れててもUbuntuではサポート内とか聞いたことがある。動作サポートなのかセキュリティサポートなのか、何のサポート課なのかまでは知らないが、星の数ほどあるパッケージをディストリごとに保守しているとしたら、これは凄いことだなと思ったし、他人が書いた得体のしれないパッケージをどう保守しているのかも気になった。

Linuxの世界は興味深い…。

nginxのダウングレードからのバージョンの復旧について

ダウングレードしても基本的に影響はないと思うが、元のバージョンに上げようとするとUbuntuそのもののバージョンアップが必要なことを知った。

しかし24.04.04 LTSから26.04への安全なアップグレードはまだ提供されていないようなのでいったん断念した。26.04.01が出ると上げられるようになるらしく、現状はお試し版みたいな感じらしい。

よくあるx.00は安定板だけど不具合がある、x.01で真の安定板になるみたいな話はUbuntuにもあるんだなと思った。

あとがき

昔nginx公式のどこかにnginxでifを使うなみたいなのがあったと思う。たぶん今はもう消えていて、GitHubに残ってる残骸に残るだけになっているようだ。

ここを見る限りifを使うとifの判定後、別のifにかかることで想定外の挙動をするから、使うならreturnやrewrite ... lastと組み合わせて、確実にリクエストを殺すようにしろということのように読めた。

公式リファレンスを見てもifそのものを使っている個所はngx_http_rewrite_moduleに存在するため、「If is Evil...」だから使ってはいけないというより、適切に使えればよいのだと思った。

あと思ったのだが、恐らくこの「If is Evil...」はnginx公式ではなく、nginx plusの方にあったドキュメントだった気がする。サイトのカラーが緑だった記憶があるからというのと、このリポジトリがそれっぽいからだ。

2026/06/16(火)WSL2の中からPowershellでOSへ通知トーストを投げる

投稿日:

PowerShellはWSL2の中から叩けるため、WSL2の中から通知を出したいときに使える。

PowerShellなのでホスト側のWindowsからも使える。

確認環境

PowerShell 7では動かないので注意。

Env Ver
OS Windows 11 Pro 25H2 (OSビルド 26200.8655)
PowerShell 5.1.26100.8655

やり方

  1. この内容をtoast.ps1など適当な名前で保存する。文字コードはUTF-8 BOM, 改行コードはLFにしておく

    param (
        [String]$subject = "WSL Notice",
        [String]$title   = "たいとるですー",
        [String]$message = "お知らせでーす",
        [String]$icon    = "C:/env/1e1b9fdf82a6a544.png",
        [switch]$keep
    )
    
    [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null
    $template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastImageAndText04)
    $xml = New-Object Windows.Data.Xml.Dom.XmlDocument
    
    $xml.LoadXml($template.GetXml())
    $toastTextElements = $xml.GetElementsByTagName("text")
    $toastTextElements.Item(0).AppendChild($xml.CreateTextNode($title)) > $null
    $toastTextElements.Item(1).AppendChild($xml.CreateTextNode($message)) > $null
    $toastImageElements = $xml.GetElementsByTagName("image")
    $toastImageElements.Item(0).SetAttribute("src", $icon) > $null
    
    if ($keep) {
        $xml.DocumentElement.SetAttribute("scenario", "reminder") > $null
        $actions = $xml.CreateElement("actions")
        $action = $xml.CreateElement("action")
        $action.SetAttribute("content", "閉じる") > $null
        $action.SetAttribute("arguments", "dismiss") > $null
        $action.SetAttribute("activationType", "background") > $null
        $actions.AppendChild($action) > $null
        $xml.DocumentElement.AppendChild($actions) > $null
    }
    
    $toast = [Windows.UI.Notifications.ToastNotification]::new($xml)
    $appId = $subject
    $notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($appId)
    
    $notifier.Show($toast)
    
  2. 次の書式で叩くと通知トーストが出る
    powershell.exe -File 'C:/path/to/toast.ps1' -subject hoge -title fuga -message piyo -icon C:/path/to/icon.png -keep
    

このスクリプトのオプション

オプション 役割
-subject 通知の表題。ここを変えると別の通知として扱われる
-title 通知のタイトル
-message メッセージ本文。一行のみ
-icon アイコン。Windowsホストの絶対パスで指定
-keep このフラグを立てると通知が消えなくなる

-subjectを変えると別の通知扱いになるため、通知を別々に貯めることができるようになる。

Windows側から叩く方法

powershell 'C:/path/to/toast.ps1' -subject hoge -title fuga -message piyo -icon C:/path/to/icon.png -keep

Windows側から叩く場合、-Fileは省略できる。

参考情報

あとがき

Claude Codeの確認と終了のイベントで通知が出ると便利かなと思って作ってみたが、まだ試せていない。

取りあえずWSL2の中と、Windowsホスト側から叩いたときに通知が出ることは確認している。

PowerShell 7で動かそうと思ったらエラーまみれで動かず、PowerShell 7の場合、NuGetパッケージを取得するか、DLLのパスを直に指定するか、サードパーティの通知ライブラリを使うかということで、諦めた。

2026/06/07(日)シェルの設定にRPS1を入れると微妙だったのでやめた話

更新日:
投稿日:

私はzshをシェルとして使っており、かれこれ5年ほどプロンプトにPROMPTとRPS1を設定していたのだが、使っていてRPS1が非常に邪魔だったのでPROMPTに統一することにした。

邪魔だったもの

これまで私は画像のようにRPS1に日時と異常終了コードを出すようにしていたのだが、複数行選択したときに必然的に巻き込んでしまう問題があった。

これはコマンドの実行ログをブログに書く時や、複数コマンドをコピペするときにRPS1の部分を除去する必要があり、手間だった。

そこでRPS1を使うのをやめてPROMPTに統一することにした。行は増えたが、こっちのほうが視線移動もなくコピペ時の巻き込み問題も減るので楽になった気がする。

他にもRPS1はターミナルの幅が狭くなったり、一部のターミナルから開くと崩れやすかったので、今回の対応でそういったこともまとめて解消されてよかった。

これは余談だがPS1でなくPROMPTを使っている理由はPS1だとRPS1を使っているときに表示が崩れる環境があったが、PROMPTだとこれが起きなかったからだ。何故かはよくわかってない。