ブログをAstro+TinaCMSからWordPressに移行した話

 この度、本ブログをAstro+TinaCMSからWordPressに移行しました。

 本記事では、WordPressの選定理由及び、移行手法について紹介します。

旧ブログの環境と問題点

 旧ブログは下記の環境で構成されていました。GitHubにMarkdownの記事データを載せるか、TinaCMSを使って記事を書くことで、Cloudflare Pagesのデプロイが自動で走り、静的サイトとして提供されるようになります。また、画像ファイルは/publicディレクトリに保存します。

  • Astro 7.1
  • TinaCMS 3.11
  • Cloudflare Pages

 本環境での問題は2点ありました。

 一つ目は画像のアップロードが少し手間であったことです。画像は/publicに保存されますから、事前に画像を圧縮しておく必要があります。また、TinaCMSは画像のアップロードを行う度にコミットを行う為、Cloudflare Pagesのビルド数制限を圧迫します。

 二つ目は下書きの問題です。私は技術系の記事を書く際、検証を行いながら、同時に本文を記述します。この場合、数日にまたがる検証や、そもそも数ヶ月掛けて気が向いたら検証を進める系の記事では、Gitにコミットできず、そのまま機材の初期化等で失われる記事が出てきます。Astroの設計でDraft記事を受け付けるようにすれば良い話ではあるのですが、プッシュしてしまうとCloudflare Pagesのビルドが走る問題もあり、あまり下書きに向いていない運用でした。

 これらの問題があったため、これらが解決できそうなWordPressを導入することにしました。

WordPressの選定理由

 真っ先に考えた移行としては、TinaCMS以外のDraftを扱えるソリューションへの移行と、Cloudinary等の画像配信サービスの導入です。

 しかし、TinaCMSはめんどくさい記事のアトリビュートを持っているこのブログにとても良くフィットしていましたし、実際に他のソリューションを入れてみたところ、あまりうまく動いてくれませんでした。

 また、このブログはアクセス数が少ないですが、それでも従量課金要素のあるCloudinary等の導入はあまり気乗りしませんでした。

 そこで、静的サイトを諦め、CMSを導入することにしました。CMSはあまり詳しくなく、とりあえず有名で、元々使ってみたいと思っていたWordPressに白羽の矢が立った訳です。実際に手元で簡単な検証を行ったところ、うまく移行出来たため、WordPressが移行先の第一候補となりました。

 OSS WordPress以外のソリューションとして、SaaSに移行するというアイデアもありました。具体的には、はてなブログやWordPress.com等です。しかし、これらのサービスはカスタムドメインが有償であり、なおかつこれまでのURLを引き継げるかの確認も取れず、丁度レンタルサーバを別用途で借りていたのもあって、自動更新などを行ってくれるOSSのWordPress運用することに決めました。

 また、AstroのバックエンドでWordPressをヘッドレスCMSのように使う選択肢もありましたが、こちらは純粋に設定の手間を考え、直接WordPressを公開することにしました。

移行手順

 逆はよくあるのでしょうが、AstroからWordPressへの移行はあまり記事がなかったように思います。今回は思い立ったのが丁度お盆休み中で、幸い記事数も少なく検証作業も簡単だったため、ChatGPTにMarkdownベースの記事一覧をWordPressのXMLエクスポートに変換するプログラムを書かせました。

 このスクリプトがかなりうまく動き、一部のMarkdownを除いてまともに読めるレベルの移行が行われていた上、問題のあるMarkdownも頑張れば読める状態であったため、このエクスポートファイルをそのまま本番の移行に使うことにしました。

 WordPressのエクスポートファイルには画像データ等が存在せず、これらのデータはサーバから落としてくる仕様の為、同一ホスト名で移行する際には問題が発生します。今回はCloudflare Pagesの.pages.devドメインが生きていたため、ここから画像ファイルを落としてくるように設定しました。

 特にコメントなども存在しなかったため、記事データの移行はこれだけで完了しました。

最後に

 WordPressへの移行は主にLLMのおかげでかなりうまくいきました。今後はカテゴリ機能等をうまく使いこなして行きたいと考えています。

 また、WordPressといえばセキュリティ問題です。一応簡単にセキュリティが上がりそうな設定は投入していますし、レンタルサーバ側も簡易的なWAFを導入してくれているようなので、これらに期待したいと考えています。現状利用しているテーマはWordPress公式の物ですし、プラグインも有名どころと思われるもの一個しか入れていないため、そこら辺の問題は少ないと思いたいところです。

 現状気になる点は、編集画面の背景が真っ白でDarkReaderも効かないため、肝心の執筆を行っていると目が痛くなることくらいでしょうか。記事ページはDarkReaderに対応しているので、おそらく本記事をご覧の方は問題無いはずです。

 今後より良いソリューションを見つけた場合、また移行を行うかもしれませんが、しばらくはWordPressの高級すぎるエディタを使って記事を書いていければと思っています。

HardwareVisualizerを起動時にUAC無しで立ち上がるようにする

最近、HardwareVisualizerというソフトウェアに出会いました。プログラム実行中は裏で常にGPU温度やプロセスの状態を記録しておき、後からそれらの情報を取得できるNetDataのようなソリューションです。

自作PCの冷却に不安を抱えていたり、ゲーム中のリソースの過不足が気になっていたりと、バックグラウンドかつ時系列での測定ソリューションが欲しいと思っており、適当にAIに愚痴ってたらこのソフトを教えてもらったため、利用するようになりました。

しかし、このソフトウェア単体ではCPU温度をまともに取得することができず、PawnIOをインストールすることでなんとかCPU温度を確認出来るようになるのですが、管理者権限が要求されます。

管理者権限が要求されるということはUACが表示されるということで、毎回起動時にUACが表示されるのは少し気になります。特にスタートアップにすさまじい量のアプリケーションを登録している関係で、タイミングが悪いとブラウジング中にUACが出ることもあります。

そこで、本記事ではUAC無しでスタートアップを行う手法について扱います。HardwareVisualizerを対象としていますが、ロジック的にはWindows標準のタスクスケジューラを利用するため、他の管理者権限を要求するアプリケーションの自動実行でも使えるはずです。

環境

  • Windows 11 Pro (25H2, 26200.9168)
  • HardwareVisualizer 1.9.2

現在GitHubのデフォルトブランチに存在するHardwareVisualizerはかなりUIが変わっているので、もしかしたら次の大幅なアップデートで手順が変わるかもしれません。

HardwareVisualizerの事前設定

事前にHardwareVisualizerの設定画面にて、下記の設定を投入します。

  1. Automatic startup on OS startupを無効に(タスクスケジューラによる自動起動と競合するため)
  2. Run as administrator on startupを有効に
  3. (オプション)Close to tray instead of quittingを有効に

タスクスケジューラによる自動起動設定

タスクスケジューラを開き、Task Scheduler Libraryもしくはお好みのフォルダを開き、そのフォルダ内でアクションメニューのCreate Taskをクリックします。

Generalでは、Nameを適当にHardwareVisualizer等と設定し、ユーザアカウントが自ユーザになっていることを確認した後、Run only when user is logged inを選択し、Run with highest priviledgesを有効にします。

同時に、Configure forをWindows 10もしくは最も新しいOSに設定します。

Triggersタブでは、新たにAt log onトリガーを作成します。ユーザは自ユーザがログインした際に制限し、それ以外の設定はデフォルトのままにします。

最後に、Actionsタブで新たなアクションを作成します。アクションはStart a programで、Program/scriptは標準では"C:\Program Files\HardwareVisualizer\hardware-visualizer.exe"となるはずです(ダブルクオーテーションは保持してください)。

もし、別のディレクトリなどにインストールした場合は、そちらに合わせて設定してください。

これらの設定を行った後、OKを押して保存します。

最後に、実際にPCを再起動したり、ログオフしたりして動作の確認を行ってください。

おまけ: CPU温度取得設定

Hardware Visualizerでは一部のセンサー情報の取得にPawnIOを要求します。Intel CPUの温度情報の取得等を行いたい場合は、PawnIOのインストールが必要です。

PawnIOはかなり強い権限を自由すぎる機能を持つドライバーです。ゲームのアンチチートツールに引っかかりそうな気もしますが、現状Strinova, NTE, 鳴潮では特に問題は起きていません。

下記にPawnIOの簡単なインストール手順を記述します。詳細は公式ドキュメントも参考にしてください。

  1. PawnIO公式サイトからインストーラーをダウンロードし、インストールします。Macintosh向けインストールDMGのように、インストール後もインストーラーを呼び出すウィンドウが残りますが、正常ですので、各自で終了させてください。
  2. PawnIO.Modulesのリリースから最新のモジュールを落としてきます。
  3. ダウンロードしたモジュール(大量の.binファイル等)をC:\Program Files\PawnIOに保存します。必要なモジュールのみを入れることもできます。

以上で設定は終了です。次回HardwareVisualizerを管理者権限で起動した際に、CPU温度がCPU Package (PawnIO Intel DTS)のような名前で表示されるはずです。

CoreServer v2でCloudflare Origin CAを使う

近年は証明書を発行すると、Certificate Transparency Log に残り、内部用サイトのドメインが流出したり、公開直後から/wp-admin等への攻撃が始まったりします。

この問題を解決する最も簡単な方法はワイルドカード証明書を発行することですが、Let’s Encrypt 等では TXT レコードの追加が求められ、CoreServer の自動発行・更新では対応できず、証明書の有効期限が年々短くなっていく昨今、手動更新もあまり現実的ではありません。

そこで、Cloudflare の発行する最長 15 年の証明書を使った Cloudflare と CoreServer 間の TLS 通信を行うことで、Certificate Transparency Log に残す証明書を Cloudflare の自動発行するワイルドカードの Edge Certificate のみにしようという試みです。

もちろん、この手法を使うには Cloudflare にプロキシさせることが条件となります。一応 Cloudflare の CA を各デバイスに配り、信用するように設定することも可能ですが、あまり良い方法とは言えないでしょう。

また、本手法では CoreServer V2 のサブドメイン登録機能を使うことで、サブドメインで提供されるサイトすべての証明書の設定を一括で終わらせられるようにしています。Cloudflare にプロキシさせたくないサイトは、サブドメインとして登録するのでは無く、ドメイン登録画面から設定し、個別に Let’s Encrypt 等の証明書を渡す必要があります。

CloudflareでOrigin CAを発行する

Cloudflare は頻繁に UI が変わるので、Cloudflare origin CA · Cloudflare SSL/TLS docs あたりを直接確認していただければと思います。

CoreServer V2 から ECC に対応していますので、Private key type は ECC にすると良いでしょう。

Hostnames に関しては APEX を使う場合、ワイルドカードに加え、APEX も登録すると良いでしょう。また、後から証明書を区別しやすいように、note--for-coreserver等のサブドメインも登録すると便利です。

また、事前にドキュメントの「Cloudflare Origin CA root certificate」セクションから、ECC の CA をダウンロードしてください。

CoreServerでドメインの設定とSSLの設定を行う

管理画面の「ドメイン」->「ドメイン管理」で、利用したいドメインを追加します。Cloudflare の無料プランの場合、登録ドメイン直下しか使えませんので、例えば「example.com」を Cloudflare に登録されている場合、CoreServer に登録するドメインは同じく「example.com」となります。

登録後、「SSL証明書設定」を開き、画面右上のドメイン名を設定したいドメインに変更します。その後、「事前に生成された証明書とキーを貼り付け」を選択し、画面の右上に現れた「SSL CA証明書」をクリックし、事前にダウンロードした Origin CA のルート証明書を貼り付け、「Use a CA Cert」にチェックを入れて保存します。

その後、1 画面戻り、鍵と証明書に Cloudflare のダッシュボードに表示された証明書を貼り付けます。

ECC を利用している場合、鍵のBEGIN PRIVATE KEY及びEND PRIVATE KEYをそれぞれ、BEGIN EC PRIVATE KEYEND EC PRIVATE KEYに変更してください。

公開するサブドメインを追加する

CoreServer の設定で、「ウェブ」->「サブドメイン管理」と進み、画面右上のドメイン名を設定したいドメインに変更します。その後、サブドメインを追加からお好みのサブドメインを登録します。

その後、Cloudflare の DNS 管理画面に当該ドメインと CoreServer の A/AAAA もしくは CNAME レコードを追加し、プロキシ設定をオンにします。

Apple containerを使ってみた

現在私の使っているMacintoshはM1 MacBook Airの8GBモデルという、なんとも言えない性能のマシンです。Apple siliconの初めてのマシンで、macOS上で動くソフトウェアはよほど無理をしない限り、8GBであることを忘れる程快適に動作してくれますが、Asahi Linuxはもちろん、macOS上であってもDockerを動かすとメモリとバッテリーをかなり消費します。

本記事では、8GB macOSにおいて、Apple containerがDockerの代わりにまともに動き、開発環境として使えるのかを検証したいと考えています。

環境

  • MacBook Air A2337 (M1, 8GB RAM, 256GB SSD)
  • container 1.0.0

使ってみる

下記に試したコマンド及び結果を記述します。

# 独自のPHPIpam Dockerイメージのビルド
# Src: https://github.com/mkaraki/phpipam-frankenphp-docker/tree/897f4c2f121d8e7c991c23c984e1bb6897b6931d
# container-runtime-linux用のVMサービスが2.13GB程度のメモリ消費
# arm64である影響で最後まで実行できず
container build -t phpipam:latest .

# さすがに動く
container run -it --rm ubuntu:noble

# 簡単なDockerfileのビルド
container build -t ipdb:latest .

# ポート待ち受けを行うApache2 PHPアプリのテスト
container run --rm -it -p 8080:80 ipdb:latest

# Volumeマウントを伴うFrankenPHPアプリケーション
container run --rm -it -p 8080:8080 -v $(pwd)/books:/books:ro cbz-viewer:latest

軽く試したところ、Containerを使い始めると、Virtual Machine Serviceが立ち上がり、メモリを2.13GB程消費し始めます。これにより、Activity Monitor上でのMemory Usedが7GB前後をうろうろするようになり、一応JetBrains IDEとMS Edgeを追加で立ち上げてもきちんと動いてはいるものの、かなり不安感はあります。この状態でCompressedが2.97GB、Swapは8.35GBです。

使っているターミナルがWarpだったり、裏でTeamsやEvernoteなどが動いていたりと、Container以外にもメモリ使用率を上げている要因はありますが、とはいえ8GBのMacBookではプログラマーになる夢を見るには少し厳しいかもしれません。

また、WSL containerと同様に、こちらもDocker Compose相当の機能を実装されていないようです。しかし、apple/container #1736にパッチが上がっているので、もしかしたら近いうちに動かせるようになるかもしれません。

Cloudflare One Clientとの相性問題

VMが53をBINDする為、mDNSResponder関係のエラーが出る場合があるとのこと。一度container system stopを行ってから、再接続しよう。Cloudflareのドキュメントによれば、再接続後に再度Container Systemを起動すれば動かせるらしいが、こちらは未検証。

Ref

WSL containerを触ってみた

環境

  • Windows 11 Pro 25H2 (OS Build 26200.8655)
  • Windows Subsystem for Linux 2.9.3
  • Git for Windows (git version 2.54.0.windows.1)

インストール

特に再起動などは要求されず、下記のコマンドを打ち、後は指示にしたがうだけで終わりました。

ただし、Docker Desktop on Windowsとの相性は悪いらしく、WSL needs updatingの画面が表示されました。現在使っているのが、Docker Desktop on Windows 4.75.0 (227598) と少し古いのが影響しているのかもしれません。

wsl --update --pre-release

使ってみる

基本は docker コマンドの代わりに wslc コマンドを叩くだけで使えます。検証するにあたり、Docker Composeが移植できるか試したかったのですが、どうやらそちらは非対応のよう。

Clystian氏 がパッチを作っているらしく、そちらはある程度試せる状態の用です。詳細は clystian/WSLのPR #1 をご参照ください。

また、公式リポジトリの Discussion #40836 及び Issue #40948 はあまり活発ではなさそうです。WSL Container自体が最近の発表かつ、Public Preview入りしたばかりですから、これはばかりはしょうがないです。

下記に実際に打ってみたコマンドを貼ります。最低限コンテナで遊ぶ分には問題なく動いてくれます。

# Ubuntuのシェルをお試し
> wslc run --rm -it ubuntu:noble

# ps等の有名なショートカットは普通に動く
> wslc ps
CONTAINER ID   NAME            IMAGE         CREATED          STATUS                 PORTS
AADC7244B1FB   noble_beartooth ubuntu:noble  16 minutes ago   running 16 minutes ago

# 独自のPHPIpam Dockerイメージのビルド
# Src: https://github.com/mkaraki/phpipam-frankenphp-docker/tree/897f4c2f121d8e7c991c23c984e1bb6897b6931d
# デフォルトだと動かない為、後述する修正を実施。
> wslc build -t phpipam:latest .

# 簡単に http://localhost:8080 で接続できることを確認
> wslc run --rm -it -p 8080:80 phpipam:latest

# マウントテスト
# 先頭に`/mnt/`を付けたりもしたが、ダメそうである。
> wslc run --rm -it -p 8080:80 -v /d/projects/phpipam-frankenphp-docker/Dockerfile:/test phpipam:latest
> wslc exec -it 1da35be50090 sh
$ cat /test
cat: /test: Is a directory

Docker Buildのお試し

前セクションで wslc build コマンドを叩きましたが、これはうまく動きませんでした。表示されたWARNING、ERRORは下記の通り。

WARNING: current commit information was not captured by the build: git was not found in the system: exec: "git": executable file not found in $PATH
ERROR: failed to solve: dockerfile parse error on line 19: unknown flag: exclude

まず、本環境にはGit for Windowsがインストールされていますが、これは認識されないようです。

そして根本的なエラーとしては、COPY 命令における --exclude オプションを認識していない。本問題の解決は容易で、ファイル先頭に # syntax=docker/dockerfile:1.25.0 とDockerfileのシンタックスバージョンを指定することで解決しました。

標準で使われているSyntaxバージョンについては調査して居ませんが、これからはSyntaxバージョンを指定するようにした方が安全かもしれません。

全体的な感想

compose コマンドや cp コマンドが無いなど、Docker Desktop on Windowsの代替として使うにはあまりにも頼りないですが、簡単なデータベースを検証用途で動かす等の用途ではある程度使えそうです。

Network系のコマンドや、Volume系のコマンドは検証から外しましたが、Docker Compose実装パッチのスクリーンショットを見る限り、こちらもうまく動いてくれそうです。

Ref

NTE上の釣りにおける高価な材料で作られた釣り餌の有効性調査

NTEの「高価な材料で作られた釣り餌」は最も安価な釣り餌の14.4倍の金額となっている。本釣り餌について、その高価さに見合う性能があるのかを簡易的に調査した。

本調査は暇つぶしで行われた、あくまでも簡易的ものであり、信頼できる品質の結果を取得することを目的としていない。

検証環境

本検証は、2026年6月3日にリリースされたNTE バージョン1.1の新釣り場である、「ヒナタ島釣場」にて行った。検証は2026年6月6日に一回のみ行われた。ランチャーの提示するバージョンは1.1.4であった。

検証では、72魚鱗コインで販売されている「幽蘭の餌」を11点購入し、これらの餌及び「上級者の釣り竿」を利用して釣れた魚に、販促文に記載されている、「ゴールデンカマス」及び「海中の栗」の出現回数を調査した。

また、同時に5魚鱗コインで購入できる「万能釣り餌」についても同様の検証を行い、取得できる経験値量及び魚鱗コインを比較する。

検証結果

最終的に、逃げられることなく11匹の魚を釣ることができた。しかし、販促文に記載されている、ゴールデンカマス及び海中の栗に関しては観測できず、釣り経験値にして合計421 Expの取得と、202魚鱗コインの取得にとどまった。取得できた経験値の中央値は25で、平均値は38であった。

実際に釣れた魚の内訳を、下記の表に示す。

Attempt # 魚種別 Exp
1 クロマグロ 24
2 ヒトデ 109
3 クロマグロ 24
4 アオノメハタ 24
5 ユカタハタ 38
6 シャインシイラ 22
7 クロマグロ 25
8 クロマグロ 25
9 藍鱗の旗 43
10 サバ 48
11 金サバ 39

万能釣り餌でも同様に、逃げられることなく11匹の魚を釣ることができた。釣り経験値は385 Exp取得し、184魚鱗コインの取得にとどまった。取得できた経験値の中央値は38で、平均値は35であった。

万能釣り餌にて釣れた魚の内訳を、下記の表に示す。

Attempt # 魚種別 Exp
1 シャインシイラ 18
2 赤鱗の旗 48
3 サバ 59
4 緑鱗の旗 38
5 クロマグロ 19
6 マンボウ 19
7 マンボウ 20
8 エンペラーエンゼル 42
9 赤鱗の旗 51
10 キリンミノカサゴ 21
11 金サバ 50

取得経験値の中央値が幽蘭の餌に比べ高いにもかかわらず、平均値及び合計値は幽蘭の餌が上回った結果となった。

t検定による検証

幽蘭の餌による経験値量及び万能釣り餌による経験値量を非等分散と仮定し、有意水準5%にて両側検定を行ったが、この2点の経験値量の平均値に有意的な差は見られなかった。

議論

本調査では、NTEでの釣りにおける高価な釣り餌の有用性について、簡易的に調査を行った結果、少なくとも11回程度の試行回数では、合計で202魚鱗コイン程度の売り上げにしかならず、釣り餌の金額である792魚鱗コインの元を取ることができなかった。

取得経験値の平均値及び合計値は幽蘭の餌が上回った結果となった原因として、幽蘭の餌において検証を行った際に、経験値量の高い、「ヒトデ」が釣れたためであると考える。ヒトデは本釣り餌の販促文に記述されていないため、偶然このような結果になったと考えられる。

本検証では、サンプル数が11件と極めて低く、外れ値と考えられるレアリティの高い魚による影響を否定できない。今後の検証では複数の釣場の利用や、試行回数を増やす必要性があると考える。

上伊那ぼたん 6話 中国語(台湾)

TinaCMSを導入したので、テスト記事の代わりに簡単にまとめてみた。中国語は全く勉強したことが無いので、内容の信憑性は皆無。

タイムスタンプはAbema TVのVOD基準。ある程度調べた後に原作2巻にすべて載っているという事実を知った。途中からはそちらの情報も含めている。

  • 7:11: 剉冰 (ツア ピン): 従来式の氷を砕くかき氷のことらしい。氷に味が付いている奴は雪花冰というらしい。
  • 8:55: 有意思 (作中ではウー イー スー、Google Translate曰くヨー イー スー): この文脈だと、「興味深い」もしくは「おもしろい」だろうか。他にも「おかしい」「意義がある」等の意味もあるらしい。食べてみたい。
  • 14:40: 同上か?: 文脈としてはあってなさそうであるため、聞き違えの可能性が高そう
  • 15:05: 我想喝水: 聞き取れなかったので原作を確認した。水をほしがっているっぽい。
    • 我: 主語
    • 想: ○○したい
    • 喝: 「飲む」という動詞
    • 水: そのまま「水」という意味

References

ソフトウェアRAIDの削除方法

Ubuntu Server 24.04等で利用されている新しいインストーラでは、/dev/md*が存在し、
ディスクがRAIDで利用されている場合、RAID無しで設定しようとするとインストール時にコケる。

元々RAID環境で使われていたストレージを利用しようとすると、
元々使っていたRAID環境が復元されるようで、
これを無効化しなければインストールに失敗する。

環境

  • Express5800 T110i
  • RAIDカード無し, AHCIモード
  • Ubuntu Server 24.04.3

手順

画面上のHelpからシェルを開き、下記コマンドでRAIDの設定状況とデバイス名を取得します。

cat /proc/mdstat

RAIDを停止し、RAIDの構成デバイスからスーパーブロックを削除します。
コントローラの仕様によっては、/dev/sda1のようにパーティションがRAIDメンバーになっているかもしれません。

mdadm --stop /dev/md126
mdadm --zero-superblock /dev/sda

昔はパーティションテーブルが残っているとインストールにコケたため、
念のためにディスクのパーティションテーブルあたりを削除しておきます。

dd if=/dev/zero of=/dev/sda bs=512M count=2

最期に再起動をすることで、RAIDブロックに起因するエラーは改善されます。

Debian 12 (x86)にATOK for Linux (atokx2)をインストールする

大昔にジャストシステムから発売されたATOK for Linux (atokx2等とも呼ばれている)をDebian 12にインストールします。

この手順でインストールしたATOKは、少なくとも環境設定が開けないという重大な問題がある。
解決策が見つかり次第、追記する。

トライアンドエラーを繰り返しまくった為、
もしかしたら必要の無い手順が入っているかもしれない。

また、DebianのIIIMFをインストールすれば改善するかもしれないが、
今回は付属のHTTとXIMで動かす。

環境及び検証内容

下記の環境をセットアップしています。
基本的にはDebianのインストーラで最小構成 + System Utilityをインストールした後、
xinitopenboxをインストールした形です。

  • Debian 12.9 i386
  • openbox 3.6.1-10
  • xinit 1.4.0-1
  • 日本語設定
    • LANG=ja_JP.UTF-8
    • XKBMODEL=pc105
    • XKBLAYOUT=jp
    • fonts-noto-cjk

下記のソフトウェアにて日本語入力を検証しました。

  • vim-gtk3 2:9.0.1378-2+deb12u2(成功)
  • xterm 379-1(成功)

既知の問題

現状、下記の問題が起きており、解決方法は不明です。

  • 環境設定等の一部ウィンドウが開かない
    • 開こうとするとXごとフリーズする
    • パレットや変換候補ウィンドウ、辞書ツール等は出る
    • 文字パレットは問題無く出る
    • BasicAux, DicUTAux, PropertyAuxが動かないでよさそう
  • (アップデート後) 上記ウィンドウを開いた後、しばらくするとXがフリーズする
    • 素早く設定してkillall xinitするしかなさそう
    • 検証が甘いので、別の原因がある気もする
  • 入力時に極端に不安定な挙動を取ることがある
    • 日本語入力仕様と思ったらフリーズするような挙動も
    • アプデで改善せず。

公式tgzパッケージの展開

doc/ATOK/readme_for_tar.htmlの通りに、下記のファイルを展開し、/にコピーする。
今回は、GTK2.4を利用する。

/bin/IIIMF/iiimf-client-lib-trunk_r2059-js1.i386.tar.gz
/bin/IIIMF/iiimf-csconv-trunk_r2059-js1.i386.tar.gz
/bin/IIIMF/iiimf-protocol-lib-trunk_r2059-js1.i386.tar.gz
/bin/IIIMF/iiimf-rc-trunk_r2059-js1.i386.tar.gz
/bin/IIIMF/iiimf-server-trunk_r2059-js1.i386.tar.gz
/bin/IIIMF/iiimf-x-trunk_r2059-js1.i386.tar.gz
/bin/IIIMF/iiimf-gtk24-trunk_r2059-js1.i386.tar.gz
/bin/ATOK/atokx-17.0-2.0.i386.tar.gz

アップデートの適用

上記のトラブルの元になる可能性があるため、必要に応じて入れる形を推奨。

公式からATOK for Linux アップデートモジュールをダウンロードし、
tar.gz内の下記のファイルを展開し、/に上書きコピーする。

bin/ATOK/atokx-17.0-2.1.i386.patch.tar.gz
iiimf-gtk24-trunk_r2059-js2.i386.tar.gz

前提パッケージのインストール

aptに存在するパッケージを入れる。

apt install libstdc++5 libgtk2.0-0

libpangox-1.0のインストール

aptに存在しなくなってしまったlibpangoxをインストールする。
Bullseye版のdebファイルをダウンロードするか、
Debian Snapshotから適当なバージョンなりソースをダウンロードする。

Systemdサービスの定義

今回はinitスクリプトは使わず、完全にSystemdから取り扱う。

/etc/systemd/system/atokx2.serviceは下記の通り。

[Unit]
Description=ATOK X2 Daemon
After=network.target

[Service]
ExecStart=/opt/atokx2/sbin/atokx2mngdaemon
Type=forking
Restart=on-failure

[Install]
WantedBy=multi-user.target

/etc/systemd/system/iiim.serviceは下記の通り。
atokx2を前提条件にしている。

[Unit]
Description=iiim (htt)

After=network.target atokx2.service
Wants=network.target atokx2.service

[Service]
ExecStart=/usr/lib/im/htt
Type=simple
Restart=on-failure

[Install]
WantedBy=multi-user.target

最期に自動起動を有効にし、同時に初回起動もしてしまう。

systemctl daemon-reload
systemctl enable --now atokx2 iiim

xinitrcを書く

~/.xinitrcに下記の内容を記述する。

#!/bin/bash
export XMODIFIERS=@im=htt
export XIM="htt"

export XIM_PROGRAM=/bin/true

export GTK_IM_MODULE=xim
export QT_IM_MODULE=xim

. /opt/atokx2/bin/atokx2_client.sh

exec /etc/X11/xinit/xinitrc

これで次にstartxした際にATOKが立ち上がる。

Debian 12 (x86)にATOK X for Linuxをインストールする

大昔にジャストシステムから発売されたATOK X for LinuxをDebian 12にインストールします。

この手順でインストールしたATOK Xは極めて不安定かつ、低速で、
変換ウィンドウやメニューすら表示されない有様ですが、
ある程度の動作確認は取れた為、現在の知識で出来る最善を記録する目的で記事にします。

トライアンドエラーを繰り返しまくった為、
もしかしたら必要の無い手順が入っているかもしれない。

また、DebianのIIIMFをインストールすれば改善するかもしれないが、
今回は付属のHTTとXIMで動かす。

環境及び検証内容

下記の環境をセットアップしています。
基本的にはDebianのインストーラで最小構成 + System Utilityをインストールした後、
xinitopenboxをインストールした形です。

  • Debian 12.9 i386
  • openbox 3.6.1-10
  • xinit 1.4.0-1
  • 日本語設定
    • LANG=ja_JP.UTF-8
    • XKBMODEL=pc105
    • XKBLAYOUT=jp
    • fonts-noto-cjk

下記のソフトウェアにて日本語入力を検証しました。

  • vim-gtk3 2:9.0.1378-2+deb12u2(成功)
  • xterm 379-1(成功)
  • kwrite(失敗, 反応せず)
  • kate(失敗, 反応せず)

既知の問題

現状、下記の問題が起きており、解決方法は不明です。

  • IMEのオンオフ切り替えが極めて遅い
    • gvim等はつられてInsertモードへの切り替えなども遅くなる
  • 変換の切り替えが遅くなる
    • 候補の二つ目くらいまでは軽量に動くが、それ以降を呼ぼうとするとかなり遅くなる
  • 変換候補ウィンドウやATOKパレットなどが表示されない
    • 入力文字種表示のみが出てくる状態
  • X全体がフリーズして操作を受け付けなくなる場合がある
    • X全体ではなくアプリケーション単位でhtt (XIM)を読ませると影響を小さく出来る
  • AtokPaletteAux, SystemLineAux, LookupAuxが継続的にセグフォする
    • segfault at 35 ip ... sp ... error 4 in libglib-1.2.so.0.0.10[...]らしい
    • 読み込ませるlibglibを書き直したら直りそうだけど、さすがに知識が足りなさすぎる

公式tgzパッケージの展開

適当なディレクトリに、CD内のatokx-1.0-1.i386.tgziiimf.tgzをコピーし、
tar xf filename.tgzで展開する。

その後、cp -R ./{etc,usr,var} /でシステムにインストールする。

init.d/functionsのインストール

CentOSのinitscriptsのソースパッケージに含まれている、rc.d/init.d/functions/etc/rc.d/init.d/functionsに保存する。

今回は、initscripts-9.03.31-2.el6.centos.src.rpmから展開した。
Wayback Machineのリンク

consoletypeのビルド

Gentooプロジェクトのgentoo-functionsから、consoletype.cをもらってくる。
コンパイルはただgcc consoletype.cすればよい。

先のinitscriptsにあるconsoletype.cをビルドしても良さそうであるが、こちらは未検証。

コンパイルしたファイルは、/sbin/consoletypeに設置する。

libxtのインストール

普通にaptで入る。
一応libc6libx11も明示的に入れておくが、
多分最初から入っていると思う。

apt install libc6 libx11-6 libxt-dev

atokx及びIIimサービスのSystemdへの登録と実行

本来はinit.dファイルをSystemd向けに書き直すべきであろうが、
めんどくさいので、そのままSystemdから呼び出す形にする。

まず、/usr/lib/systemd/system/atokx.serviceは下記のようになる。
IIimの後に起動するようにしているが、特に要らない気もする。

[Unit]
Description=ATOK X Server
After=IIim.service

[Service]
Type=forking
ExecStart=/etc/rc.d/init.d/atokx start
ExecStop=/etc/rc.d/init.d/atokx stop

[Install]
WantedBy=default.target

/usr/lib/systemd/system/IIim.serviceは下記の通り。
こちらはsimpleで直接実行した方がエラー時の復旧的にもよいと思う。

[Unit]
Description=IIim

[Service]
Type=forking
ExecStart=/etc/rc.d/init.d/IIim start
ExecStop=/etc/rc.d/init.d/IIim stop

[Install]
WantedBy=default.target

2つとも設置できたら、下記のコマンドで起動してしまう。

systemctl daemon-reload
systemctl enable --now atokx IIim

xrdbの配置

aptでx11-xserver-utilsをインストールした後、
下記のコマンドで/usr/X11R6/binの中にxrdbのシンボリックリンクを置く。

mkdir -p /usr/X11R6/bin
ln -s /usr/bin/xrdb /usr/X11R6/bin/xrdb

GTK1.2のインストール

aptにはもう存在しないため、
GNOMEプロジェクトからglib-1.2.10.tar.gzgtk+-1.2.10.tar.gzをダウンロードしてくる。

glibのインストール

ダウンロードしてきたglibのパッケージを展開し、
gstrfuncs.cを修正する。

おそらくこの修正は間違ったアプローチであるが、
現状これしか解決策が思い浮かばないので、
そのまま編集してしまう。

下記にpatchファイルを貼る。
適当にファイルに保存し、
patch < saved-patch-file.patchすれば適用されるはず。

--- gstrfuncs.c    2025-09-08 20:32:11.237763156 +0900
+++ gstrfuncs.c.patched 2025-09-08 16:31:52.089892394 +0900
@@ -867,8 +867,8 @@
                   /* beware of positional parameters
                    */
                 case '$':
-                  g_warning (G_GNUC_PRETTY_FUNCTION
-                             "(): unable to handle positional parameters (%%n$)");
+                  g_warning (G_GNUC_PRETTY_FUNCTION);
+                             /* "(): unable to handle positional parameters (%%n$)"); */
                   len += 1024; /* try adding some safety padding */
                   break;

@@ -1034,8 +1034,8 @@
                   /*          n   .   dddddddddddddddddddddddd   E   +-  eeee */
                   conv_len += 1 + 1 + MAX (24, spec.precision) + 1 + 1 + 4;
                   if (spec.mod_extra_long)
-                    g_warning (G_GNUC_PRETTY_FUNCTION
-                               "(): unable to handle long double, collecting double only");
+                    g_warning (G_GNUC_PRETTY_FUNCTION);
+                               /* "(): unable to handle long double, collecting double only"); */
 #ifdef HAVE_LONG_DOUBLE
 #error need to implement special handling for long double
 #endif
@@ -1077,8 +1077,8 @@
                   conv_done = TRUE;
                   if (spec.mod_long)
                     {
-                      g_warning (G_GNUC_PRETTY_FUNCTION
-                                 "(): unable to handle wide char strings");
+                      g_warning (G_GNUC_PRETTY_FUNCTION);
+                                 /* "(): unable to handle wide char strings"); */
                       len += 1024; /* try adding some safety padding */
                     }
                   break;
@@ -1108,9 +1108,9 @@
                   conv_len += format - spec_start;
                   break;
                 default:
-                  g_warning (G_GNUC_PRETTY_FUNCTION
-                             "(): unable to handle `%c' while parsing format",
-                             c);
+                  g_warning (G_GNUC_PRETTY_FUNCTION);
+                             /* "(): unable to handle `%c' while parsing format",
+                             c); */
                   break;
                 }
               conv_done |= conv_len > 0;

パッチの適用が終わったら、Configureとmake、make installを行う。
今回はインストール先を変更したいため、prefixを設定する。
また、コンパイルエラーをなくすために、いくつかのむちゃくちゃなオプションも指定する。

CFLAGS='-fcommon -D__const__=__volatile__' ./configure --prefix=/usr/local/gtk-1.2
make
make install

もしシステム全体にインストールしたい場合は、
prefixを明示的に/にする。
設定したprefixgtk+のインストールでも同じ値を設定する。

gtk+のインストール

こちらも展開し、下記のコマンドでconfigureとmake、make installを行う。
パッチの適用は特に必要無い。

LD_LIBRARY_PATH=/usr/local/gtk-1.2/lib:$LD_LIBRARY_PATH GLIB_CONFIG=/usr/local/gtk-1.2/bin/glib-config CFLAGS='-fcommon' ./configure --prefix=/usr/local/gtk-1.2
make
make install

もし、先ほどのセクションでシステム全体にglibをインストールした場合は、configureコマンドを下記の要に変更する。

CFLAGS='-fcommon' ./configure --prefix=/

EUC-JPのロケール生成

/etc/locale.genja_JP.EUC-JPの行をコメントを外し、
locale-genコマンドを実行して適用する。

システム全体のロケールを変更する必要は、
Fefora Core 1がUTF-8であることを考えるとなさそう。

libXi.soのインストール

aptでlibxi-devをインストールする。

Fedora Core 1向けのインストール手順を踏襲する為の手順のため、
もしかしたら飛ばせるかもしれない。

飛ばす場合は、atokx_clientスクリプトのLD_PRELOADも設定しないように。

atokx_clientスクリプトの編集

/usr/lib/im/locale/ja/atokserver/atokx_clientを編集する。

/usr/lib/im/httx -if atok12 -lc_basiclocale ja_JP -xim htt_xbe &

と書いてある行を、下記のように変更する。
LD_LIBRARY_PATHはGTK1.2をシステム全体に入れた場合は要らない。

LD_PRELOAD=/usr/lib/i386-linux-gnu/libXi.so LD_LIBRARY_PATH=/usr/local/gtk-1.2/lib:$LD_LIBRARY_PATH LANG=ja_JP.eucJP /usr/lib/im/httx -if atok12 -lc_basiclocale ja_JP -xim htt_xbe &

自動起動スクリプトを書く

httxがそれなりの頻度で落ちるため、
自動で再起動するスクリプトを用意する。

本資料では、これを~/.htt_helper.shに置く。
chmod +xを忘れないように。

#!/bin/bash

while true; do
    htt_proc=`ps x | grep "/usr/lib/im/httx" | wc -l`

    if [ $htt_proc -lt 2 ]; then
        logger -is -p user.info -t htt_helper "httx might crashed or not booted. Restarting."
        . /usr/lib/im/locale/ja/atokserver/atokx_client
    fi
done

xinitrcを書く

~/.xinitrcに下記の内容を記述する。

上記の自動再起動スクリプトを使わない場合は、~/.htt_helper.shの行をコメントアウトし、
1行上にある純正のローダを呼び出す行のコメントを外す。

#!/bin/bash
export XMODIFIERS=@im=htt
export XIM="htt"

export XIM_PROGRAM=/bin/true

export GTK_IM_MODULE=xim
export QT_IM_MODULE=xim

#. /usr/lib/im/locale/ja/atokserver/atokx_client
~/.htt_helper.sh &

exec /etc/X11/xinit/xinitrc

参考資料

nginxで全ポートをlistenする

nginxで全ポートをlistenする方法です。
実験がてら作ってみた方法ですから、実際にこのような事をしたい場合は、
iptablesでREDIRECTする方が良いでしょう。

この手法を取ると、システム全体でネットワーク接続を発生できなくなります。

今回はどうしてもserver_portを利用したかったので、
このような力業を利用しました。

環境

  • Debian 12 Bookworm
  • nginx-full 1.22.1-9+deb12u1 (Debianのパッケージ)

ポート利用状況の確認

下記のコマンドでポートをLISTENしているプロセスが無いか確認します。
もしLISTENしているプロセスがあれば、そのポートを利用しない事を選択するか、
LISTENしているプロセスの停止を検討してください。

lsof -i | grep LISTEN

nginxのインストール

今回は、server_tokenoffにしたいため、nginx-fullをインストールします。

apt install nginx-full

nginxの設定

まず、nginx.confserver_tokens off;をコメントアウトし、
サーバのバージョン情報などを秘匿します。

65535ポートをv4とv6でlistenするため、
worker_connectionsworker_rlimit_nofileを余裕を持って200000に設定します。

worker_rlimit_nofileはファイル先頭のworker_processesあたりに、
worker_connectionseventsセクションに設定します。

limits.confの設定

/etc/security/limits.confwww-dataユーザの最大ファイル数を設定します。
先ほど設定した、worker_rlimit_nofileの値よりも大きい値を設定してください。

www-data soft nofile 200000
www-data hard nofile 200000

sysctlの設定

/etc/sysctl.confに下記の設定を追加します。
先ほどと同じように、fs.file-maxの値は、worker_rlimit_nofileの値よりも大きい値を設定してください。

fs.file-max = 200000

設定変更後、下記のコマンドで適用します。
この後再起動をするので、下記のステップは省略しても良いです。

sysctl -p

systemdの設定

/etc/systemd/system.conf[Manager]セクションにある、DefaultLimitNOFILEを設定します。
この値も、worker_rlimit_nofileの値よりも大きい値を設定してください。

[Manager]
# 省略
DefaultLimitNOFILE=200000

コメントアウトされている行ですから、コメントアウトして編集しても良いですし、
最後の方に追記してもかまいません。

サイトの設定

listenディレクティブは下記のようになります。
この例では、listenしたいインターフェイスのIPアドレスを1.2.3.4cafe::1:2:3:4にしています。
環境に応じて変更してください。

listen 1.2.3.4:1-65535;
listen [cafe::1:2:3:4]:1-65535;

システムの再起動を行う

limites.confsystemdの設定を行ったので、再起動を行います。
デフォルトでnginxが起動するはずですから、動作確認も同時に行ってください。

参考サイト

  • https://www.antitree.com/2017/06/running-nginx-on-all-ports/
  • https://unix.stackexchange.com/questions/366352/etc-security-limits-conf-not-applied
  • https://serverfault.com/questions/279262/nginx-proxy-a-large-port-range-to-equivalent-port-on-a-different-ip-address

FortiGateでフレッツ光クロスのXpass 固定IP1を収容する

なぜか公式ドキュメントに記載されていない、DHCPv6-PDで収容する方法です。
OCX光のドキュメントのおかげで何とか収容できたので備忘として書いておきます。

環境

WANポートの設定

portAに10GBASE-Tのトランシーバを接続し、下記のコンフィグを投入します。
投入する際、set ip6-upstream-interface "portA"の箇所は必ず最後に入れてください。

もしportAに割り当てるアドレスを変更したい場合、ip6-subnet ::1/64の下位64ビットを変更してください。

config system interface
    edit "portA"
        set lldp-reception disable
        set lldp-transmission disable
        set role wan
        config ipv6
            set ip6-mode delegated
            set dhcp6-prefix-delegation enable
            set ip6-delegated-prefix-iaid 1
            set ip6-subnet ::1/64
            config dhcp6-iapd-list
                edit 1
                    set prefix-hint ::/56
                next
            end
            set ip6-upstream-interface "portA"
        end
    next
end

nd-proxyの設定(要るかは不明)

おそらく不要だとは思いますが、動いている物を触って壊したくはないので無くても動くかは未検証です。
もし動かなかったら入れてみてください。

config system nd-proxy
    set status enable
    set member "portA"
end

VNEインターフェースの設定

VNEインターフェースの設定です。FortiOS 7.6ではconfig system vne-tunnelが無くなり、vne-interfaceになっています。
公式Cookbookは、DS-Liteだけなぜかvne-tunnelのままですので修正を加えます。
editの中は従来の方法と同じように書けます。

これまではvne.rootとなっていたインターフェース名ですが、edit "xpass"の箇所を変更することで、手動で指定することができるようになりました。
また、update-url?は、シリアルコンソールでつないだ状態で、一度Ctrl + vを押し、その後?を押すことで入力できます。
この際、ターミナルソフトウェアにCtrl + vのシュートカットが割り当てられていないことを確認してください。

config system vne-interface
    edit "xpass"
        set interface "portA"
        set ipv4-address 17.123.123.123 255.255.255.255
        set br "ipv6 add"
        set update-url "..."
        set mode fixed-ip
        set http-username "..."
        set http-password "..."
    next
end

SD-WANへの割り当て

一般的なインターフェースを割り当てるようにxpassと言うインターフェースを割り当ててください。
この際、ゲートウェイは0.0.0.0のままで動作します。

SD-WANを使用していない場合も、Static Routeで同じように指定すれば動作します。

参考資料

MicrosoftのHigh Volume Emailを使う

現在ベータで提供されているMicrosoft 365のHigh Volume Emailの設定を行います。

Security Defaultsを無効化する

Microsoft Entra admin centerにて、Security defaultsを無効化し、
Conditional Accessを代わりに利用するようにします。

Entra admin centerのIdentityセクションにあるOverviewを選択し、
Propertiesタブを開きます。

一番下にSecurity defaultsの設定がありますので、ここから無効にしてください。
無効にする際に、Conditional Accessを代わりに利用する設定にすることを推奨します。

また、削除理由にHigh Volume Emailを使うためであることを記述すると、
将来的にMicrosoftが何かしらの方法を作ってくれるかもしれません。
是非記述しましょう。

詳しい設定の意味等はMicrosoft DocsのSecurity defaults in Microsoft Entra IDに記述されています。

High Volume Emailを利用するアカウントのグループを作成

次のConditional Accessで例外設定をするためにMicrosoft Entra admin CenterでSecurity Groupを作成します。

High Volume Emailで独自のメールドメインから送信する場合は、
下記のMembership ruleがそのまま利用できます。

(user.mail -contains "@domain.to.use.invalid")

このルールはセキュアでは無いことに注意してください。
本来であればendsWith等で明示的にこのメールがドメイン部であることを示すべきですが、
悲しいことにMembership ruleではstartsWithのみ対応のようです。

もしメールのプレフックスでHVEメールを示す場合は、startsWithでよりセキュアに設定できるでしょう。

下記のコードは動作検証していませんが、おそらく使えるはずです。

(user.mail -startsWith "system.hve.")

Conditional Accessの設定

Security Defaultsの設定画面まで移動すると、
Manage Conditional Accessというリンクが見えるようになっているはずです。
これをクリックし、Conditional Accessの設定に入ります。

本来であればBlock legacy authenticationの例外に先ほど作成したグループを設定すればいいはずですが、
念のためにMultifactor authentication for all usersにも同様に例外設定をし、
同時にStateをReport-onlyに設定しています。

この設定はとても危険ですので、一度例外設定を投入したのち、
しばらく放置して動くか確認すべきです。
もし動いたらIssueページから教えてもらえると助かります。

ドメインの追加

Microsoft Docs – Add a domain to Microsoft 365を参考に、
ExchangeとDKIMの設定を投入したドメインの追加を行います。

ここはおそらくExchangeを使っているテナントの場合は過去に設定している場合がほとんどだと思いますので、特に躓くことなく設定できるかと思います。

また、現在利用しているドメインからそのままメールを送信する場合、この手順はスキップできます。

HVEアカウントの作成

Exchange admin centerのMail flowセクションの中にあるHigh volume mailからHVEアカウントを作成します。

プライマリメールアドレスがメールの送信元になります。
また、同一テナント内に送信する場合は、表示名がFromの表示名より優先されるため、
わかりやすい名前を指定することを推奨します。

AllowBasicAuthSmtpポリシーの適用

Exchange admin centerのCloud Shellで下記のコマンドを実行し、
Exchangeの設定をコマンドでできるようにします。

Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline

最初にAllowBasicAuthSmtpの設定を持つポリシーの作成を行います。
下記のようなコマンドが利用できます。
また、一度ポリシーを作成した後は複数のHVEアカウントや一般のアカウントで使いまわすことができるため、この作業は最初の1回のみで大丈夫です。

New-AuthenticationPolicy -Name "AllowBasicAuthSmtp" -AllowBasicAuthSmtp

作成したHVEアカウントに作成したポリシーを割り当てます。
下記のようなコマンドを実行します。

Set-User -Identity "[email protected]" -AuthenticationPolicy "AllowBasicAuthSmtp"

メーラーへの設定

Microsoft DocsのManage high volume emails for Microsoft 365 Public previewに記述されている接続先をSMTPクライアントに設定します。

日本語版ドキュメントでは、smtp-hve.office365.comとなるべきホスト名がsmtp-have.office365.comと誤訳されているので注意してください。

また、ユーザ名とパスワードは送信元メールアドレスとHVEアカウント作成時に設定したパスワードとなります。

この記事の最後にはエラーコードとその原因が書いてありますので、必要に応じて参照してください。

Windowsの3本指タップをブラウジング向けカスタマイズにする

Windowsの3本指ジェスチャーは標準だとデスクトップを表示や、検索など、人によっては使わないものが多いです。
今回はマウス中ボタンとタブ切り替えに設定し、ブラウジングに便利な設定にします。

3本指タップを設定

Windowsの設定から、「Bluetoothとデバイス」->「タッチパッド」->「3本指ジェスチャー」を開きます。
タップを「Windows Search」から「マウスの中ボタン」に設定すればOKです。

この状態では、下記のショートカットが利用できます。

  • ブラウザでリンクを3本指タップすると新しいタブで開かれます
  • ブラウザのタブを3本指タップするとタブが閉じられます
  • Windowsタスクバーのアプリケーションを3本指タップすると、すでに開かれていても、新しいウィンドウで開かれます

3本指ジェスチャーの設定

Windowsの設定から、「Bluetoothとデバイス」->「タッチパッド」-> 「詳細ジェスチャー」->「3本指ジェスチャーの設定」を開きます。

「上へスワイプ」を「カスタム」に設定し、「記録を開始」を押し、「Ctrl + Shift + Tab」を入力し、「記録を終了」をクリックします。
「下へスワイプ」も同じように設定しますが、「Ctrl + Tab」を入力します。

この状態では、下記のショートカットが利用できます。

  • ブラウザなどのタブが使えるアプリケーションでタブの切り替えがジェスチャーでできるようになります
  • Edgeを縦タブ設定にすることで、直感的に操作できるようになります

FessとnginxでPDFを保管する全文検索可能なサーバを構築する

目的

PDFやdocs,xlsxなどを全文検索できるサーバを構築します。
nginxを使い、データにオンラインでアクセスできるようにします。

環境

  • Ubuntu 22.04 LTS

Nginxのセットアップ

Nginxをインストール

Ubuntuにnginxをインストールします。
server_tokensの設定も行うため、nginx-extrasも同時にインストールします。

sudo apt install nginx nginx-extras

Nginxのグローバル設定

/etc/nginx/nginx.confの20行目付近にあるserver_tokens off;をコメントインし、
nginxのバージョンが公開されないようにします。

Sitesの設定

/etc/nginx/sites-available/datastore.confを以下のように編集します。

server {
        listen 80 default_server;
        listen [::]:80 default_server;
        root /var/www/content;

        server_name _;

        add_header  X-Robots-Tag "noindex, nofollow, nosnippet, noarchive";

        autoindex on;
        charset utf-8;

        location = /robots.txt { return 200 "User-agent: *\nDisallow: /\n"; }

        location / {
                autoindex on;
                allow 192.168.0.0/16;
                allow 172.16.0.0/12;
                allow 10.0.0.0/8;
                deny all;
        }
}

location /allowは適切な社内ネットワークなどを指定してください。
外部に公開する場合はdeny allごとこれらを削除し、
Robots系の設定も削除してください。

/var/www/contentにディレクトリを作成し、PDFなどを入れてください。

サイトを有効化し、デフォルトサイトを無効化します。

sudo ln -s /etc/nginx/sites-available/datastore.conf /etc/nginx/sites-enabled/datastore.conf
sudo rm /etc/nginx/sites-enabled/default

Nginxの再起動

設定を反映させるため、nginxを再起動します。

sudo systemctl reload nginx

OpenSearchのインストールと設定

OpenSearch公式ページからdeb形式でOpenSearchをダウンロードするか、aptリポジトリを追加してインストールします。

おすすめはaptリポジトリを使う方法です。

下記コマンドから必要なプラグインを、インストールしますが、
2.10.0の部分はインストールしたOpenSearchのバージョンに合わせてください。

$ sudo /usr/share/opensearch/bin/opensearch-plugin install org.codelibs.opensearch:opensearch-analysis-fess:2.10.0
$ sudo /usr/share/opensearch/bin/opensearch-plugin install org.codelibs.opensearch:opensearch-analysis-extension:2.10.0
$ sudo /usr/share/opensearch/bin/opensearch-plugin install org.codelibs.opensearch:opensearch-minhash:2.10.0
$ sudo /usr/share/opensearch/bin/opensearch-plugin install org.codelibs.opensearch:opensearch-configsync:2.10.0

最後に/etc/opensearch/opensearch.ymlに下記設定を追記します。

configsync.config_path: /var/lib/opensearch/data/config/
plugins.security.disabled: true

Javaのインストール

Fessのクロールに必要なJavaをインストールします。

FessはUbuntu PackagesのJava JREを使うとクラッシュするため、
Temurinを利用します。

公式ドキュメントを参考に、
apt Repositoryを設定し、temurin-17-jreをインストールしてください。

Fessのインストールと設定

Fessのインストールをする前にFessにい外部からアクセスする必要がある場合、
Fessは標準でIPv6のListenを行います。
もし、IPv4をListenさせたい場合は、
/etc/sysctl.confに下記内容を追記してsysctl -pを実行し、
IPv6をシステムで無効にしてください。

net.ipv6.conf.all.disable_ipv6 = 1

FessはGitHubのリリースからdebパッケージをダウンロードしてインストールします。

wget https://github.com/codelibs/fess/releases/download/fess-14.10.1/fess-14.10.1.deb
sudo apt install ./fess-14.10.1.deb

/usr/share/fess/bin/fess.in.sh内の次の2行をコメントインし、内容も修正します。

SEARCH_ENGINE_HTTP_URL=http://localhost:9200
FESS_DICTIONARY_PATH=/var/lib/opensearch/data/config/

OpenSearchとFessを自動起動させる

systemctlで下記のコマンドを投入し、
サービスを開始させ自動起動を有効にします。

sudo systemctl daemon-reload
sudo systemctl restart opensearch.service fess.service
sudo systemctl enable opensearch.service fess.service

Fessの設定を行う

http://localhost:8080/adminにアクセスし、管理画面に入ります。

初期ユーザはadmin:adminです。

スケジューラー設定

System -> SchedulerにJob Schedulerが存在しない場合があります。
初期で何もない場合は、System Info -> Back UpからGitHubで公開されてる初期設定をインポートしてください。

クロールの設定を行う

公式ドキュメントを参考にクロール設定を追加してください。

このNginx設定例ではrobots.txtでクロールを制限しているため、
Config Parametersに下記の設定を投入してください。

crawler.ignore.robots.txt=true
config.ignore.robots.tags=true
client.robotsTxtEnabled=false

また、必要に応じて、インデックス化する最大のファイルサイズを指定してください。
単位はバイトです。

client.maxContentLength=262144000

クロールの実行

System -> SchedulerからDefault Crawlerを開き、
Start nowをクリックすることでクロールが開始されます。

ジョブの進捗はSystem -> Job Logから、
クロール結果はSystem -> Crawling Infoから確認できます。

内部に蓄積されたインデックス済みファイルは、
System -> Searchで空文字を検索することで閲覧できます。

ログについて

Fessのログは/var/log/fess下に出力されます。

Crawlerを呼ぶ前のログはfess.logに、
Crawler自体のログはfess-crawler.logに保存されます。

Mailjetを使ったメール送信サーバをUbuntu22.04とPostfixで作る

目的

Zabbixなどのメールを配信するサーバをMailjetを使って構築します。
Mailjetを使うことで、OP25Bが行われているプロバイダでもメールを送信できるようにします。

Postfixのインストール

libsasl2-modulesがないと認証で失敗するため、同時にインストールします。

Postfixの設定はNo configで続行してください。

apt install libsasl2-modules postfix 

Postfixの設定

Postfixの設定例です。
実際の拠点で使っているものを記述しているので、
いくつか不要な表記があると思います。
各自で消してください。

relayhost = in-v3.mailjet.com:587
smtp_sasl_auth_enable = yes
smtp_use_tls = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous

command_directory = /usr/sbin
daemon_directory = /usr/lib/postfix/sbin
data_directory = /var/lib/postfix

myhostname = example.com
mydomain = example.com

local_recipient_maps =

mail_owner = postfix

myorigin = $mydomain
smtpd_banner = $myhostname ESMTP

inet_protocols = all
inet_interfaces = all
mynetworks_style = subnet
mynetworks = 127.0.0.0/8

smtpd_relay_before_recipient_restrictions = yes
smtpd_relay_restrictions =  permit_mynetworks, reject_unauth_destination
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination

setgid_group = postdrop

message_size_limit = 10485760
mailbox_size_limit = 0
compatibility_level = 3.6

認証情報の設定

/etc/postfix/sasl_passwdは次の内容になります。
ホスト名指定がin-v3ではなくinのみになっていることに注意してください。

in.mailjet.com APIKey:SecretKey

適用

最後にpostmapを実行し、Postfixを再起動します。

sudo postmap hash:/etc/postfix/sasl_passwd
sudo systemctl restart postfix

Mattermostをdocker-composeとCloudflare TunnelでUbuntu Server 22.04上に構築する

はじめに

今回構築するMattermostは下記の構成になります。

  • Port 8065でHTTP Listen
  • Cloudflare Tunnelでリバースプロキシ
  • Callsは利用しない
  • Bleveは利用しない
  • S3は利用しない

このレッスンでは下記の環境を自身で用意してください

  • x64 CPUを搭載したPC (Dockerが動作すること)
  • 上記のPCでDVDもしくはUSBからブートさせる機材
  • DVD-RとDVDドライブもしくは4GB以上のUSBメモリ

このレッスンでは、コンピュータ内のデータが消去されます。
すべての操作は慎重に行ってください。

もしレッスンを行うにあたって不安な場合、
担当者の空き時間をあらかじめ確認し、その時間に合わせてレッスンを行ってください。

Ubuntu Server 22.04のインストール

Ubuntuは2年おきに長期サポート版がリリースされます。
2022年4月にリリースされた22.04が現在の最新リリースであり、
次の長期サポート版は2024年4月リリース予定の24.04です。

この資料では22.04を利用して環境を構築しますが、
基本最新の長期サポート版を利用してください。
長期サポート版はダウンロード時などにLTSと表記されます。
参考にしてください。

Ubuntu Serverのダウンロード

Ubuntu Serverは公式サイトのダウンロードページからダウンロードできます。
Alternative downloadsからTorrentなどでダウンロードすることもできます。
必要に応じて活用してください。

日本のミラーサイトからダウンロードすることもできます。
詳しくはUbuntu Japanese Teamのページを参照してください。

Ubuntu Serverのインストール

基本はUbuntu公式ドキュメント
Server Worldの記事
を参考にするといいでしょう。

サイトと違う点として、
インストールする際にはUbuntu server (minimized)を選択してください。

ネットワークの設定についてはかなり癖があります。
とりあえずDHCPのネットワークで設定を実施してください。
固定IPでの設定は別に記事にします。

OpenSSHサーバは必ずオンにしてください。
これ以降はSSHでの操作を行います。

Dockerを使うと記述していますが、
インストール最後のアプリケーションをインストールする画面では何も選択しないでください。

IPアドレスの確認

インストール時に設定したユーザ名とパスワードでまずPC本体でログインします。

$ 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: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 18:66:da:2f:e1:b4 brd ff:ff:ff:ff:ff:ff
    inet 17.0.0.2/24 brd 17.0.0.255 scope global enp2s0
       valid_lft forever preferred_lft forever
    inet6 2620:149:af0::10/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 2591920sec preferred_lft 604720sec

ip aコマンドでIPアドレスを確認してください。

基本的にenpethから始まる物が有線LANで、inetの行にIPアドレスが記載されています。
この場合、17.0.0.2がIPアドレスで、/24がサブネットマスクです。

IPv6アドレスも同じようにinet6の行で確認できます。

このIPアドレスをメモしておいてください。

SSHでのアクセス

Windows 10からはSSHクライアントが標準でインストールされています。

SSHコマンドの基本文法は下記のとおりです。

usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface]
           [-b bind_address] [-c cipher_spec] [-D [bind_address:]port]
           [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11]
           [-i identity_file] [-J [user@]host[:port]] [-L address]
           [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
           [-Q query_option] [-R address] [-S ctl_path] [-W host:port]
           [-w local_tun[:remote_tun]] destination [command

基本的に使うのは-l, -p, -L, destinationでしょう。

-lはログインするユーザ名、
-pはポート番号、
-Lはポートフォワーディング(本ドキュメントでは利用しません)の設定です。

destinationでは宛先(サーバ)を設定します。

初期設定の場合下記のコマンドでログインできます。

ssh -l 初期設定で作ったユーザ名 サーバのIPアドレス

最初にアクセスする際には下記の表示が出ます。

The authenticity of host 'サーバのIPアドレス' can't be established.
ED25519 key fingerprint is SHA256:ABCDEF0123456789.....
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?

yesと入力しEnterを押してください。

その後、パスワードを要求されます。
パスワードの入力時には文字が一切表示されませんが、正常な挙動です。

下記のような画面が出ればログインできています(もっと少ない場合もあります)

Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-53-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.

Last login: Tue Aug  8 01:46:27 2023 from 17.0.3.129
ユーザ名@サーバ名:~$

試しにip aなどのコマンドをうち、
サーバ本体で打った時と同じ値になるか試してみましょう。

基本コマンドについて

基本的なファイル操作などについては、LearningDocsで解説しています。
実際に試してみてください。

下記では、Learning Docsで解説していないコマンドを解説します。

sudo

Linuxにはrootという特権ユーザが存在します。
rootではおおよそ大体の(破壊を含む)すべての行動ができます。
その危険性から、Ubuntuではrootユーザは初期状態で無効化
(パスワードが設定されておらずログインできないユーザ)
になっていますが、特権ユーザとして実行しないといけない処理
(アプリケーションのインストール等)
を行う際にはsudoコマンドを利用し、特権ユーザに成り上がります。

sudoコマンドは下記のように使います。

sudo 特権で実行したいコマンド

例えば、aptコマンドはアプリケーションのインストールやアップデートを行うコマンドですが、
特権ユーザでないと実行できません。

$ apt update # 通常ユーザで実行
Reading package lists... Done
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
E: Unable to lock directory /var/lib/apt/lists/
W: Problem unlinking the file /var/cache/apt/pkgcache.bin - RemoveCaches (13: Permission denied)
W: Problem unlinking the file /var/cache/apt/srcpkgcache.bin - RemoveCaches (13: Permission denied)

$ sudo apt update # sudoを使って実行
[sudo] password for ユーザ: # ここでパスワードを入力(一定期間sudoしてないと表示される)
Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease
Get:2 http://archive.ubuntu.com/ubuntu jammy-updates InRelease [119 kB]
Get:3 http://archive.ubuntu.com/ubuntu jammy-backports InRelease [109 kB]
Get:4 http://archive.ubuntu.com/ubuntu jammy-security InRelease [110 kB]
Get:5 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages [868 kB]
Get:6 http://archive.ubuntu.com/ubuntu jammy-updates/main Translation-en [212 kB]
Get:7 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 c-n-f Metadata [15.6 kB]
Get:8 http://archive.ubuntu.com/ubuntu jammy-updates/universe amd64 Packages [964 kB]
Get:9 http://archive.ubuntu.com/ubuntu jammy-updates/universe Translation-en [209 kB]
Fetched 2,613 kB in 4s (686 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
26 packages can be upgraded. Run 'apt list --upgradable' to see them.

sudoとても危険なコマンドです。
なんでもsudoに頼らず、本当にroot権限が必要か、
そもそも今行おうとしている作業が本当に正しいのかをよく確認してください。
大いなる力には大いなる責任が伴います。

apt

aptはDebian系のLinuxで利用されるパッケージ管理システムです。

基本的には下記の構文で主に利用されます。

$ sudo apt update # パッケージ情報の更新
$ sudo apt upgrade # パッケージの更新
$ sudo apt install パッケージ名 # パッケージのインストール
$ sudo apt remove パッケージ名 # パッケージのアンインストール
$ sudo apt purge パッケージ名 # パッケージの設定ごと削除
$ sudo apt autoremove # 不要なパッケージの削除
$ sudo apt autopurge # 不要なパッケージの設定ごと削除
$ apt search パッケージ名や検索ワード # パッケージの検索

基本的に、aptコマンドで何かしらの作業をする前に、
必ずapt updateを行ってください。

aptコマンドでは、パッケージの情報をローカルに一度保管するため、
ローカルのデータが古いと様々なコマンドが失敗します。

Dockerとdocker-composeのインストール

Dockerはコンテナ型の仮想化技術です。
Kernelレベルでの仮想化を行うため、
仮想化ソフトウェアを利用するよりも軽量で高速に動作します。

また、イメージという概念でアプリケーションの展開を行うため、
とてもめんどくさい環境構築も比較的楽になります。

Docker公式のマニュアルを読むのが一番良いでしょう。

インストールする際は最新のバージョン
(英語的にはLatest Version)をインストールしてください。

Docker Composeも同じように公式ドキュメントを参考にインストールしてください。

最後にインストールできているか確認しましょう

$ docker --version
Docker version 24.0.5, build ced0996

$ docker-compose --version
docker-compose version 1.29.2, build unknown

値が違っても構いません。
エラーが出ていないことを確認してください。

DockerとDocker Composeで遊ぶ

さて、Dockerで遊んでみましょう。

試しに

$ sudo docker run --rm -it ubuntu:latest bash

などと実行し、Ubuntuのイメージを実行してみましょう。

シェルにroot@ランダムな文字列:/#と表示されれば成功です。

この環境はあくまで仮想環境です。
rm -rf /*などを打っても多分大丈夫だと思います(責任は取りません)

exitで抜けましょう。

Docker Composeは少し便利になったDockerです。

通常Dockerでは、ネットワークなどで接続性を用意する場合、
それはもうめんどくさい手順が必要ですが、
Docker Composeでは同一のYamlファイル内のコンテナは
初期状態で同一のネットワークに接続され、Yaml内のキーの名前で名前解決できるため、
DBが必要なアプリケーションの構築などでとても便利です。

Dockerとdocker-composeについて説明しようとするとかなり長くなるので、
詳しくはググるか個別で質問して解決してください。

覚えておくべきこと

Dockerではコンテナとイメージがよく出てきます。
イメージからコンテナが作られ、コンテナ内で様々な事象が起こります。
コンテナは不要になれば破棄できます。

イメージが同じであれば、基本的には同じ内容コンテナが生成されます。

永続化

Volumeを使うと、コンテナの特定のディレクトリやファイルなどを、
現実のシステム上のディレクトリやファイルにマウント(若者的にはリンクとか言った方がいい?)できます。
これにより、コンテナ内のデータを永続化できます。

試してみましょう

あらかじめホストでls /tmpを実行し、中身をなんとなく覚えておいてください。

docker run --rm -it -v /tmp:/hosttmp:ro ubuntu:latest bash

このコマンドでコンテナを構築し、ls /hosttmpを実行すると大体同じ内容になっているはずです。
:roをつけているため、touchなどを実行しようとしても弾かれると思います。

ポート開放

Exposeという概念があります。
Dockerでは標準でネットワークに対しホストのIPでNAPT(e-Worldの解説)されるため、
Exposeを使い明示的にポートを指定してアクセスを許可する必要があります。

例えば、

docker run --rm -it -p 8080:80 nginx:latest

で8080ポートでnginxにアクセスできます。

試しにブラウザでhttp://サーバのIP:8080/にアクセスしてみてください。
Welcome to nginx!が表示されるはずです。

Ctrl + Cの同時押しで終了しましょう。

Mattermostの構築

推奨される手順は公式ドキュメントに記述されていますが、
今回は独自流で進めます。

Mattermost用にディレクトリを作り、その中に移動します。
今後はその中で主に作業を行います。

.envファイルを作り下記の内容にします。
ただし、コメントは削除してください(日本語が不具合を起こすかもしれないので)

# Mattermostを公開するドメインを設定してください。
# cloudflaredで公開できるドメインを設定してください。
DOMAIN=mattermost.example.com

# タイムゾーン設定です
# 日本ならAsia/Tokyoそれ以外は
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
# を参照してください。
TZ=Asia/Tokyo

# PCが再起動した際にどのようにするかの設定です。
# always: 停止されていた場合でも再起動時に起動する
# unless-stopped: 停止されていなければ再起動時に起動する
# on-failure: エラーで停止した場合のみ再起動する
RESTART_POLICY=unless-stopped

# Postgresデータベースのバージョンです。
# https://hub.docker.com/_/postgres
# に書いてある最新のbetaやalphaとついていないバージョンを指定しるとよいでしょう。
POSTGRES_IMAGE_TAG=15-alpine
# Postgresの永続化先です
# このディレクトリを削除するとデータベースが消えます。
POSTGRES_DATA_PATH=./volumes/db/var/lib/postgresql/data

# Postgresのユーザ名、パスワード、データベース名です。
# この値をMattermost側で設定し、MattermostがDBを使えるようにします。
POSTGRES_USER=mmuser
POSTGRES_PASSWORD=mmuser_password
POSTGRES_DB=mattermost

# Mattermostの設定ファイル関連の永続化設定です
MATTERMOST_CONFIG_PATH=./volumes/app/mattermost/config
MATTERMOST_DATA_PATH=./volumes/app/mattermost/data
MATTERMOST_LOGS_PATH=./volumes/app/mattermost/logs
MATTERMOST_PLUGINS_PATH=./volumes/app/mattermost/plugins
MATTERMOST_CLIENT_PLUGINS_PATH=./volumes/app/mattermost/client/plugins
MATTERMOST_BLEVE_INDEXES_PATH=./volumes/app/mattermost/bleve-indexes

# Bleve index (全文検索)の設定です
# いじらないでください。
MM_BLEVESETTINGS_INDEXDIR=/mattermost/bleve-indexes

# 課金している場合は`mattermost-enterprise-edition`に変更してください。
# それ以外は`mattermost-team-edition`のままにしてください。
MATTERMOST_IMAGE=mattermost-team-edition
# バージョンは
# https://hub.docker.com/r/mattermost/mattermost-team-edition/tags
# https://docs.mattermost.com/install/self-managed-changelog.html
# の2つの両方にある物を選択してください。
# 現状の最新は8.0です。
MATTERMOST_IMAGE_TAG=8.0

# Mattermostの公開ポートです。
# そのまま使うわけではないので8065にしたままにすることを推奨します。
APP_PORT=8065

# データベースの設定です。
# 変更しないでください
MM_SQLSETTINGS_DRIVERNAME=postgres
MM_SQLSETTINGS_DATASOURCE=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=disable&connect_timeout=10

# Mattermostの公開URL設定です
# 特定ポートで公開したい場合などは編集する必要がありますが、
# 今回の設定では不要です
MM_SERVICESETTINGS_SITEURL=https://${DOMAIN}

docker-compose.ymlを作り下記の内容にします。

version: "2.4"

services:
  postgres:
    image: postgres:${POSTGRES_IMAGE_TAG}
    restart: ${RESTART_POLICY}
    security_opt:
      - no-new-privileges:true
    pids_limit: 100
    read_only: true
    tmpfs:
      - /tmp
      - /var/run/postgresql
    volumes:
      - ${POSTGRES_DATA_PATH}:/var/lib/postgresql/data
    environment:
      - TZ
      - POSTGRES_USER
      - POSTGRES_PASSWORD
      - POSTGRES_DB

  mattermost:
    depends_on:
      - postgres
    image: mattermost/${MATTERMOST_IMAGE}:${MATTERMOST_IMAGE_TAG}
    restart: ${RESTART_POLICY}
    security_opt:
      - no-new-privileges:true
    pids_limit: 200
    tmpfs:
      - /tmp
    volumes:
      - ${MATTERMOST_CONFIG_PATH}:/mattermost/config:rw
      - ${MATTERMOST_DATA_PATH}:/mattermost/data:rw
      - ${MATTERMOST_LOGS_PATH}:/mattermost/logs:rw
      - ${MATTERMOST_PLUGINS_PATH}:/mattermost/plugins:rw
      - ${MATTERMOST_CLIENT_PLUGINS_PATH}:/mattermost/client/plugins:rw
      - ${MATTERMOST_BLEVE_INDEXES_PATH}:/mattermost/bleve-indexes:rw
    environment:
      - TZ
      - MM_SQLSETTINGS_DRIVERNAME
      - MM_SQLSETTINGS_DATASOURCE
      - MM_BLEVESETTINGS_INDEXDIR
      - MM_SERVICESETTINGS_SITEURL
    ports:
      - ${APP_PORT}:8065

docker-compose up -dで実行します。
docker-compose logs -fでログを確認できます。

ログが出力されなくなったらCtrl + Cで終了しましょう。

Cloudflaredのインストール

今回はCloudflare Tunnel
でサーバを公開します。

Cloudflare packagesを参考にaptでCloudflaredをインストールできるようにします。

インストールが終わったらcloudflared --versionでインストールが正常にできているか試してみましょう。

$ cloudflared --version
cloudflared version 2022.10.3 (built 2022-10-26-1030 UTC)

Cloudflaredの設定はCloudflareの公式ドキュメントを参照してください。
Cloudflareは明らかにいい方向に向かっていますが、UIの変更が多いため、ここで説明しても多分すぐ変わります。

Public Hostnameで設定するローカルアドレスはhttp://localhost:8065です。
Additional application settingsは不要です。

Connect a networkセクションはスキップしてください。

動作確認

最後に、Mattermostにドメイン越しでアクセスできるか試してください。

初期設定も必要に応じて行ってください
(本来は初期設定は公開前に行ってください。セキュリティ事故が起こります)

docomo新プランeximo・irumoと過去プランの比較

2023/06/20時点で公開されている情報をもとに作成

割引・特典なし

500MB 1GB 3GB 5GB 6GB 7GB 9GB 10GB 20GB 60GB 100GB 無制限
eximo 4,565 5,665 7,315
5G ギガホ プレミア 5,665 7,315
ギガホ プレミア 5,555 7,205
irumo 550 2,167 2,827 3,377
ギガライト 3,465 4,565 5,665 6,765
ahamo 2,970 4,950
OCN モバイル ONE 550 770 990 1,320 1,760

WindowsをSSLインスペクション環境で利用する

メモ記事です。
私が困難に直面し次第、追記をします。
IssueとかPR投げてもらえれば反映するかもしれません。

Python

pipを使いWindowsの証明書を利用できるようにするパッケージを入れる。
現状、requestsで動作確認済み。
venv先にもインストールする必要がある。

pip自体もSSLを利用するため、明示的にいくつかのホストをTrustedさせている。

pip install pip-system-certs --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org

PHP

php.ini[curl][openssl]セクションに記述します。

[curl]
curl.cainfo =c:\fortigate.pem

[openssl]
openssl.cafile=c:\fortigate.pem

動作確認はphp -a

curl_exec(curl_init("https://ifconfig.io"));

などでいいと思います。

pfSenseを透過ファイアウォールとして設定する

普段はFortinetに魂を売っている筆者ではあるが、
さすがに各VMホストに導入するためだけにFortiGate-VMを購入していては破産するため、
pfSenseでお手軽ファイアウォールをするために透過ファイアウォールの設定を行う。

pfSenseは簡単に透過ファイアウォールを設定することができないので、
将来の私向けのメモとして記録を残す。

環境

  • pfSense 2.6.0

手順

インストール・WAN/LAN設定

インストール後にWAN/LAN設定がある、
後々のACL記述でWAN/LANの概念が存在するのため、
VMの外をWAN、VM内をLANとした。

IPアドレス割り当て

WEB UIにアクセスするためにWAN/LANのどちらか好きな方にIPアドレスを割り当てる。

ここで設定した値は後程消すことになるので、ある程度適当でも構わない。

また、使わないインターフェースはアドレス設定を空白で入力し、
アドレス無しで設定すると幸せになれるかもしれない。

WebUIへのアクセス・初期設定

admin:pfsenseでアクセスできる。
初期設定は適当に済ませるとよい。

WAN側から設定画面にアクセスしたい場合はShellから、

pfctl -d

でファイアウォールを一時無効化できる。

設定値は基本的に今後も使うが、
IPアドレス設定はどうせ消すため、適当でよい。

Bridgeを作る

Web UIでInterfaces -> Assignments -> Bridges -> AddからBridgeを作り、
WANとLANを追加する。

System -> Advanced -> System Tunablesから設定を開き、
net.link.bridge.pfil_bridge1にする。

Interface -> Assignmentsから、
BRIDGE0をAddし、OPT1を作る。

NATをオフにする

NATは不要なので、
Firewall -> NAT -> Outboundで設定に入り、
Disable Outbound NAT rule generationを指定する。

IPアドレスを設定する

WANとLANのIPv4/6 Configuration TypeをそれぞれNoneに設定する。

OPT1にIPv4/IPv6アドレスを最適な値に指定する。

OPT1はおそらくWANとLANをWeb UIから削除した後にCLIで設定するとよいだろう。

ルールの書き方

ファイアウォールルールでは、LAN・WAN・OPT1をすべて利用できる。

そのため、最低限様々な通信を通したい場合、
すべてのセクションにおいてとりあえずAllow allをするとよいだろう。

FortiGateの購入を考えている人へ

この記事では、FortiGateを購入しようか迷っている人向けに、
様々な代替品や自宅ネットに向いているかどうかについて記述します。

代替案

FortiGateは多くの場合4kからご購入いただけます。
もし、コンピュータやVMハイパーバイザをお持ちの場合は実際の使用感をお試しいただけます。

Sophos Firewall Home Edition

Sophos社はイギリスのセキュリティソフトウェア・ハードウェアベンダです。

Sophosは無償ツールとして、
Sophos Firewall Home Editionを提供しています。

システム要件は高いですが、UTMアプライアンスを購入する前に試す感覚で利用してみるといいでしょう。

FortiGate-VM

FortiGate-VMはFortiGateのVMイメージ版です。
VMのため、ハードウェアアクセラレーションが利用できませんが、使用感を確認する用途では十分です。

FortiGate-VMは優勝製品ですが、製品デモが存在します。
実機を導入する前に一度使ってみるとよいでしょう。

FortiGateの選び方

製品名の見方

FortiGate製品の製品名は基本、下記のフォーマットで記述されています。

FortiGate nnX

FortiGate: シリーズ名
nn: 任意の数字 多くの場合、2-4桁
X : アルファベット1文字

Xは世代を表します。2023/01/17時点ではFが最新世代です。

nnは機種の世代内での優位性を表します。
多くの場合、数字が大きくなれば上位機種になります。
また、1桁目は多くの場合、機能が追加されたものを表します。
例えばFortiWifiシリーズの50EとFWF-51Eは、内部ストレージの有無が異なります。
(Data Sheet)

FortiWifiシリーズは、FortiGateにWi-Fiアクセスポイント機能が追加されたものです。

製品の選び方

OSサポートで選ぶ

FortiGate製品は同一世代の場合でもサポート内容が異なる場合があります。
例えば、50Eと60Eは同一世代ですが、50EはOSが6.2まで対応なのに対し、60Eは現状最新版である7.2に対応しています。
(参考)

この問題は顕著に影響し、50EのOSの最終サポートは2023/9/28ですが、60Eは2026/9/30まで行われ、
もし次期OSにも対応するのであればこの期限はさらに伸びます。
(参考)

追加された機能で選ぶ

OSサポートは追加された機能に顕著に影響します。

例えば、MAP-Eサポートなどは6.4以降であり、
50Eは対象外
(参照)
になります。

基本機能で選ぶ

基本的な機能は各FortiGateのデータシートを参照してください。

また、OSごとにFeature Platform Matrixが公開されています。
こちらを参照することで、各製品の大まかな機能や制限を確認することができます。

性能で選ぶ

基本的な性能はは各FortiGateのデータシートを参照してください。

例として、当環境では50EはSSLインスペクションを行うと、80Mbps-100Mbpsほどのスループットを記録します。

お持ちのForti製品との連携で選ぶ

FortiGateは同じFortinet社の製品と強い連携が可能です。

例えば、FortiAnalyzerをお持ちの場合、
公式ドキュメントのCompatibility with FortiOSセクションを確認し、
お持ちのFortiGateがどのFortiOSに対応しているか確認してください。

FortiGateでセキュリティ上の恩恵を受けることができるか調べる

FortiGate 50Eの場合、確認できた限り下記の通信を監視することができます。

  • 特定のSSL通信
  • SSL通信の中身 (CA証明書のインストールが必要)
  • SSL証明書
  • 中身のインスペクションが可能
  • HTTP
  • SMTP
  • POP3
  • IMAP
  • MAPI
  • FTP
  • CIFS
  • DNS (53)
  • 通信があったことの確認・ブロックが可能
  • Application Signaturesに登録されている通信

また、QUICなどの対応していないプロトコルの通信も存在します。

これ以降は、特記すべき点が存在する機能について記述します。
また、各機能は基本ライセンス無しで運用できますが、定義ファイルの更新にはライセンスが必要です。

SSLインスペクション

SSLインスペクションを行う際は、基本的にCAルート証明書のインストールが求められます。
また、Androidなどの一部OSや製品はSSLインスペクション状態で一部機能が正常に動きません。

そのため、AndroidやGoogle HomeなどのデバイスはSSL証明書インスペクションへの切り替えが必要です。

SSLインスペクションにライセンスは必要ありません。

QUICなど、インスペクションできない通信も存在します。

AntiVirus

マルウェアのHashを読ませることで、ライセンス無しでAntiVirus機能が利用できますが、
本体に保存できるHashの数を考えると実用的ではありません。

Web Filter

Web Filter機能はライセンス無しで利用できますが、
FortiGuard category based filterがオンの場合はすべての通信がブロックされます。

YouTubeチャンネル制限はFortiOS 6.2.12では現状利用できません。

また、File Filterにおいて、動作状況が確認できないフィルター設定が存在します。

DNS Filter

DNS Filter機能はライセンス無しで利用できますが、
FortiGuard category based filterは利用できない可能性があります。

FortiGate所有の注意点

FortiGateを所有される際は、
上記のセキュリティ機能の特記事項に加え、
下記の点について十分注意してください。

ファームウェア

FortiGateではライセンス契約を行っていない場合、
正規の方法でファームウェアを取得できません。

脆弱性

FortiGateはUTMシェア1位という立場上、
セキュリティ脆弱性が多く発見されています。

VPN機能などを利用するうえでFortiGateに外部からアクセスできるようにする場合、
FortiGateのファームウェアを最新のものにするなど、セキュリティ対策を怠らないでください。

おわりに

筆者はFortiGate 50Eのオーナーですが、FortiGateはライセンスがあって輝きます。

しかし、ライセンスが無くても十分輝ける余地を持っている良い子です。
(あと、かっこいい)

購入前にこの記事をよくご確認いただき、
幸せなインターネットライフをぜひFortiGateとお過ごしください。

個人的なFortiの設定

この記事では、他の環境にも転用が効きそうなFortiGateの設定を記述します。

基本的に私が使っているFortiGateに合わせて随時更新していくと思います。

前提

  • FortiGate 50E
  • FortiOS 6.2.12

更新履歴

日時 内容
2023-01-11 初版

Security Fablic

Settings

Cloud Loggingを有効に設定、
頻度はRealtimeを選択

Fabric Connectors

Policy & Objects

IPv4 Policy

先頭に

  • Feodo Trackerリストからの通信をDROP (Logあり)
  • Feodo Trackerリストへの通信をDROP (Logあり)

を追加

Security Profiles

AntiVirus

  • Detect Viruses: Block
  • Inspected Protocols: すべてOn
  • APT Protection Options: すべてOn
  • Original File Destination: お好みで (私はDiscard)

Web Filter

  • FortiGard category based filter: お好みで (ライセンスがない場合はOff)
  • File Filter
  • Log: On
  • Scan Archived Contents: On
  • List:
    • Deny password protected
    • Protocols: HTTP + FTP
    • File types: 7z, rar, zip
    • Action: Block
    • Direction: Incoming
    • Match Password Protected Files: On
  • Search Engines: お好みで
  • Static URL Filter
  • Block invalid URLs: On

DNS Filter

  • FortiGuard category based filter
  • Remote CategoriesにFabric Connectorsで指定した定義があるのでブロック
  • それ以外はお好みで、個人的には
    • Malicious Websites: Block
    • Phishing: Block
    • Spam URLS: Block
    • Dynamic DNS: Monitor
    • Newly Observed Domain: Monitor
    • Newly Registerd Domain: Monitor
    • Unrated: Monitor
  • Static Domain Filter
  • External IP Block Lists: Fabric Connectorsで指定した定義があるのでブロック
  • Options
  • Allow DNS requests when a rating error occurs: お好みで (私はOm)
  • Log all DNS queries and responses: On

Application Control

  • Categories: ProxyとP2Pをブロック、それ以外はMonitor
  • Options
  • Allow and Log DNS Traffic: Yes
  • QUIC: Block

Intrusion Prevention

  • Obfuscated.JavaScript.Access: Allow, Disable Logging
  • Seveity 3-5: Block, Log
  • Seveity 2: Default, Log
  • Scan Outgoing Connections to Botnet Sites: ライセンスがあるならBlock

Email Filter

  • Enable Spam Detection and Filtering: On
  • Span Detection by Protocol: お好みで
  • FortiGuard Spam Filtering: すべてOn
  • Local Spam Filtering: Black White List以外On
  • File Filter: すべてOn

SSL/SSH Inspection

別で記事を用意します。

Updater.classマルウェアの本体部分の考察

この記事はUpdater.classファイルがダウンロードする
kernel-certs-debug4917.logファイルを簡単にのぞき見を行い、
考察を行った。

はじめに

筆者は専門家では無く、
リバースエンジニアリングを隅々まで行ったわけではない。
本記事内には見当違いな場所もあると思われる。

外部との通信

URLは踏めないようにしているが無害化は行っていない。
間違ってアクセスしないように十分注意すること。

このプログラムは下記と接続を行う:
http://t23e7v6uz8idz87ehugwq <dot> skyrage <dot> de/version
http://t23e7v6uz8idz87ehugwq <dot> skyrage <dot> de/qqqqqqqqq
ssl://qw3e1ee12e9hzheu9h1912hew1sh12uw9 <dot> skyrage <dot> de:17929

実際の通信内容はAny.Runからpcapをダウンロードできるためそれを見ていただいたほうが良いとは思うが、qqqqqqqqqはjarファイル (VirusTotal)で、versionは数値データ (921) の入ったテキストファイルであった。

ssl通信について

SSL通信であるため中の通信は覗けなかったが、プログラムを確認した知人がいうには独自仕様の通信ではないかとの意見があった。

サーバ側の証明書は下記のものが利用されていた。

> openssl x509 -in key.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            26:aa:65:34:32:16:cf:c8:08:16:02:73:56:b8:4f:13:d8:73:77:7f
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
        Validity
            Not Before: Jul 18 16:25:40 2022 GMT
            Not After : Jul 15 16:25:40 2032 GMT
        Subject: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:ab:5a:5d:ae:36:ed:5f:21:43:a3:32:c3:a7:66:
                    4b:43:97:4a:ee:61:c2:d2:30:2d:13:4e:02:a3:8d:
                    1b:89:4e:13:15:be:4b:d6:82:7f:44:ae:3d:4a:a7:
                    b1:50:5a:f2:6a:76:a6:55:f9:1a:1e:84:de:e5:a8:
                    56:60:8b:40:11:21:bb:dc:79:56:f9:fc:b7:7b:28:
                    ca:16:a6:37:cf:a4:4e:a6:de:d6:07:6c:8b:88:20:
                    df:b0:3b:69:70:43:a2:46:fe:2d:76:63:bb:2b:bf:
                    97:bb:03:1f:1c:a3:46:3e:9d:40:c8:21:61:98:4f:
                    ce:95:84:b0:35:f2:da:8d:1d:ef:7c:9d:ec:a9:61:
                    ce:8d:b0:f8:50:bd:8a:69:b3:66:80:e6:31:10:b1:
                    b4:00:c2:51:0e:e7:30:d9:34:c7:26:38:07:50:50:
                    75:82:a3:e6:97:56:e6:26:ef:5f:0d:d3:bc:7c:61:
                    2f:f4:d6:55:96:3e:a0:ed:c4:19:ee:42:aa:7d:f1:
                    2b:43:e2:20:4a:5c:31:99:d0:84:a5:82:30:3f:ca:
                    42:84:94:3d:ac:3f:eb:a1:ac:81:c5:02:d0:cd:ee:
                    83:99:a8:7d:26:74:a6:65:e0:16:6f:81:5d:f7:64:
                    8a:fe:ed:3f:cc:08:06:4c:a7:b3:1b:b4:7d:da:7b:
                    17:33
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                50:D7:07:2A:09:4A:78:A7:FF:88:45:84:6F:B5:42:BC:DF:C1:51:6C
            X509v3 Authority Key Identifier:
                keyid:50:D7:07:2A:09:4A:78:A7:FF:88:45:84:6F:B5:42:BC:DF:C1:51:6C

            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: sha256WithRSAEncryption
         0a:d3:f9:c6:20:ad:69:c7:44:42:ae:95:5c:bb:4a:b5:47:ba:
         98:03:e2:20:a0:8c:cc:fb:77:15:dc:ac:4d:be:f4:5c:05:38:
         ed:a3:87:b5:15:2d:8d:b6:a6:00:8b:76:f7:82:71:ae:af:7e:
         01:36:cf:6b:27:cd:f5:06:3e:c3:54:13:a4:a0:07:50:00:e6:
         46:98:20:41:bf:32:ae:c9:42:56:81:f5:e2:07:e1:d7:7d:52:
         20:e4:81:a6:df:f9:4c:06:ef:a0:fd:7e:0a:ec:a6:4e:bc:ed:
         03:42:1f:d4:cb:e9:79:b9:b4:d3:9f:8d:1b:58:52:d2:b1:d2:
         94:02:8b:ed:07:43:18:3e:c8:65:c5:dd:cc:64:a5:23:99:a9:
         44:f8:5f:3f:6e:2a:fe:9f:4c:e3:26:d5:19:27:51:a7:7a:d6:
         77:9d:11:b3:4f:a0:90:1a:6b:c6:de:c8:6f:f6:33:83:4c:3b:
         11:8f:1b:11:3e:0a:07:15:5e:5e:43:ce:4e:70:e5:90:cf:84:
         b7:43:ff:03:fe:fd:6e:fb:ee:fb:1a:ec:7e:17:ec:20:36:cc:
         87:5c:a3:57:21:5b:29:9e:71:d9:aa:50:f6:a7:ed:57:97:7b:
         8b:34:2a:8d:64:79:9b:eb:f7:89:52:39:95:17:8c:f1:3a:a9:
         46:da:a0:a7

自己署名されたものであり、CAが設定されていない。

ST = Some-Stateとなっているところはおそらく詰めが甘かった部分ではないかと思う。

そして、おそらくこの通信がこのプログラムのキーとなる部分ではないかと考える。

被害を抑える方法

今回のプログラムが実行された際の被害を抑える方法としては、
– サーバがアクセスするFQDN, IPをホワイトリスト制にする
– DNSなどでそもそも引っかからないようにする
– 指定されたDNS以外への通信をリジェクトする
– SSL通信をすべてInspectし、CA証明書のチェックも強制する
– FortiGateのライセンスがない機材でも、当該の設定を導入したところ通信がクローズされるようになった

などが考えられる。

また、現状主要な商用エンドポイントセキュリティソフトでの検知が可能であるため、サーバ上に商用のエンドポイントセキュリティを入れ、定期的なスキャンを掛けることでも早期発見につながった可能性がある。

Updater.classマルウェアの自己増殖について

この記事ではリバースエンジニアリングというより自己増殖の過程をお見せします。

ここでいう.logファイルは
VirusTotal上のこちらのファイルの事を指します。

検証環境

  • Docker
  • mcr.microsoft.com/openjdk/jdk:17-ubuntu

はじめに

実際にサーバアプリケーションを使いプラグインを感染させた挙動は、
Any.Runでご確認いただけます。

実際に実行した際のログ
はGistに張っておきます。
空のZipファイルを入れていた関係でエラーだらけですが、
書き換え対象のファイルは判別できるかと思います。

筆者はセキュリティ専門家ではありません。
見当違いなことを言っている箇所が多いと思います。

挙動

挙動はとてもシンプルです。
HDD内のすべてのjarファイルに対して、変更を試みます。
ファイルを直接writeでオープンするのではなく、
同じディレクトリ内に.tmpで終わるファイルを作ってからそれを上書きコピーして保存を行うため、Any.Run上では上書き扱いの警告が出ていません。

プラグイン別の実装

完全にコードを読んだわけではありませんが、
少なくとも下記をincludeしているものに対しては特殊な書き換えを行うようです。

  • net/labymod/api/LabyModAddon
  • onEnableに対し、書き換えを実施
  • net/md_5/bungee/api/plugin/Plugin,
    org/bukkit/plugin/java/JavaPlugin
  • onLoadもしくはonEnableにインジェクション

リバースエンジニアリングについて

やはり難読化されています。

今回記事で取り扱っているものは、
JADXで解析できたうち、mainメソッドから簡単に追えた範囲のみです。

被害を防ぐために

今回のマルウェアは
MCAntiMalware
で検知可能でした。
また、自己増殖をするため、ファイルのハッシュを厳格にチェックする機構や、
厳しいACLと監査ログがあれば、同じように被害を防げた可能性があります。

Kea DHCPをSamba ADDCのDDNSとHot-standby HAで構築した話

前提

  • Ubuntu 22.04
  • Kea 2.2.0

Kea DHCPをインストールする

ISC公式が用意しているリポジトリからKeaをインストールしてください。

2022/12/26日時点で、
https://cloudsmith.io/~isc/repos/
で公開されており、
最新バージョンである2.2.0はこちらからアクセスできます。

Samba AD DCと連携させる

Samba AD DCのDNS機能を使い、DDNS風の動作をさせる例です。

設定スクリプトの準備

dhcp-dyndns.sh

/etc/kea/kea-dhcp-dyndns.sh
に保存してください。

また、スクリプト内の設定を必要に応じて変更してください。

hooks librariesの設定をする

下記のような設定を投入してください。

"hooks-libraries": [
    {
        "library": "/usr/lib/x86_64-linux-gnu/kea/hooks/libdhcp_run_script.so",
        "parameters": {
            "name": "/etc/kea/kea-dhcp-dyndns.sh",
            "sync": false
        }
    }
]

ドメインに参加させる

必要パッケージをインストールする

apt install winbind krb5-user samba

netコマンドが実行できれば成功です。

smb.confを記述する

[global]
   kerberos method = secrets and keytab
   realm = YOUR.DOMAIN.EXAMPLE.COM
   workgroup = YOUR
   security = ads

参加コマンドを打つ

Administratorユーザで参加する場合は下記のコマンドで参加できます。

net ads join -U Administrators

DNS編集ユーザを作る

パスワードは利用しないのでランダムで設定。

ユーザ名と説明文はお好みで。

samba-tool user create dhcpduser --random-password --description='Unprivileged user for DNS updates via ISC DHCP server'
samba-tool user setexpiry dhcpduser --noexpiry
samba-tool group addmembers DnsAdmins dhcpduser

keytabを出力

Samba AD DCが動いているマシン上で下記のコマンドを実行し、
dhcpduser.keytab
を入手します。

samba-tool domain exportkeytab [email protected] dhcpduser.keytab

入手したkeytabファイルはDHCPサーバの/etc/dhcpduser.keytabにコピーしてください。

権限の設定を忘れずに行ってください。

HA構成を作る

前提パッケージをインストールする

apt install isc-kea-ctrl-agent

リモート接続設定を変更する

/etc/kea/kea-ctrl-agent.confを編集します。

http-host0.0.0.0(もしくは適切な値)に変更してください。

HA設定を追加する

下記の設定を適宜変更して投入する。

libdhcp_lease_cmdsを入れないと正常に動かない(リース情報を共有できない)ので注意。

"hooks-libraries": [
    {
        "library": "/usr/lib/x86_64-linux-gnu/kea/hooks/libdhcp_lease_cmds.so",
        "parameters": { } 
    },
    {
        "library": "/usr/lib/x86_64-linux-gnu/kea/hooks/libdhcp_ha.so",
        "parameters": {
            "high-availability": [{
                "this-server-name": "dhcp01",
                "mode": "load-balancing",
                "heartbeat-delay": 10000,
                "max-response-delay": 10000,
                "max-ack-delay": 5000,
                "max-unacked-clients": 5,
                "peers": [{
                    "name": "dhcp01",
                    "url": "http://17.0.1.1:8000/",
                    "role": "primary",
                    "auto-failover": true
                }, {
                    "name": "dhcp02",
                    "url": "http://17.0.2.1:8000/",
                    "role": "secondary",
                    "auto-failover": true
                }]
            }]
        }
    }
]

マインクラフトにて観測されたUpdater.classマルウェアの検証

当記事内には実際に攻撃者が利用したURLなどが無毒化した状態で記述されている。
もし開く場合は自己責任で。

時系列

  • 2022/12/27 10:18: サーバが正常に起動していない現象を観測
  • サーバ管理担当者がサーバを再起動
  • java.net.NoRouteToHostException: No route to hostエラーを観測
  • レンタルサーバ事業者にネットワーク設備の点検を依頼
  • 2022/12/27 10:30: レンタルサーバ事業者から、障害が発生していない報告を受ける
  • マルウェア検査アプリケーションでマルウェアを発見
  • 2022/12/28 10:35: 障害の復旧作業に筆者が合流
  • 2022/12/29 02:00: 当該障害がクリティカルなセキュリティ事故であることが判明
  • 2022/12/30 10:56: 当該サーバが復活し、当初のエラーが出なくなっている可能性があることが発覚
    これに伴い、VirusTotal, Any.Runの結果を記事内に追記
  • 2022/12/31 02:00: 感染していた場合でも、エラー無しでサーバが正常に動作することが判明

はじめに

本記事ではプラグインファイル・Paperバイナリに対して感染したUpdater.classについて取り扱う。

それ以外の項目については、
こちらの記事(英語)が参考になると思われる。

また、実際に感染したサーバを実行した際の動作について
Any.Run
で実験を行っている。
そちらも見ていただけると、本記事と別途記述している2記事についてもよくご理解いただけるのではないかと思う。

エントリーポイントの汚染

複数のmainメソッドにおいてUpdater.init()を呼び出すコードが発見されている。

また、コードとして


public static void main (String[] arrstring) {
    Updater.init();
    String[] args;
}

のように変更されており、
引数が編集されていることで書き換え済みか認識しているのではないかと考察した。

また、CFRでの解析においてUpdaterクラスが認識出来ていなかったが、
おそらくUpdater.classファイルに不正な値を入力することで、
解析アプリケーションをまともに動かせなくする目的があったのではないかと考える。

Updater.init()の挙動

リバースエンジニアリングした全文は
こちら
を参照していただきたい。

また、筆者が必要に応じてアノテーションを付けたファイルは
こちら
から利用できる。

前提バイナリのロード

Updater.classでは
最初にjava.io.tmpdir内の
kernel-certs-debug4917.logというファイルに対して
Fileオブジェクトを生成する。

もし、すでにkernel-certs-debug4917.logファイルが存在しているのであれば、
当該ファイルをjavaもしくはjavaw.exeで実行する。

拡張子は.logであり、いかにも一般的なファイルに擬態させているが、中身はjarファイルである。

バイナリのダウンロード

もしkernel-certs-debug4917.logが存在しない場合、次の動作が行われる。

  1. 初期値として0Prpx2ekKWc=をロード
  2. リソース内の/plugin-config.binからIJMZR7mQs8faH0sBuSYr8g==をロード
  3. ttp:// files <dot> skyrage <dot> de/mvdからjarファイルをを.logとして保存
    (VirusTotal,
    詳細記事)
  4. 1もしくは2でロードした値を-Dgnuに代入し、ダウンロードしたバイナリを実行
  5. ttp:// files <dot> skyrage <dot> de/updateからzip形式のファイルをダウンロード
    (VirusTotal,
    Any.Run,
    詳細記事)
  6. ダウンロードしたファイルを加工(詳細は割愛)
  7. ダウンロードしたファイルを実行

追跡

Whois

Whoisの最終変更は下記のとおりである。

Changed: 2021-07-12T21:50:02+02:00

また、ネームサーバはCloudflareの物が利用されていたようだ。

当該マルウェアについて本チームの考察

共同で研究を行った のふれむ氏 の調べたところによると、
当該マルウェアは2022年の8月ごろから発見されていると見て良いのではないかと思われる。

当チームが観測したバージョンは、
おそらく2022/12/27日時点でCloudflare側が規約違反もしくはFreeプランの制限超過で
Proxyを解除し、それによりCloudflare以外からの通信を拒否していたサーバにアクセスできなくなったことで
No route to hostがエラーとして出るようになり、発覚に至ったと考えられる。

また、今回感染したファイルは
MCAntiMalware

Kasperskyのウイルス対策ソフトウェアで検出が可能だった
ようである。

Pluginを導入する前に
Virus Total
などで検査するだけでも十分防げた可能性は高い。

当該のマルウェアに関する他の記事

  • https://ljskatt.no/analysis/updater_class/
  • https://www.spigotmc.org/threads/1-19-1-fatal-error-converting-plugin-updater-class.567801/
  • https://goli-carft.com/minecraft-malware-announcement/

分散化についていろいろ

注意: Decentralizedを完全に誤解してそうな人の記事です。娯楽としてどうぞ

分散化=インターネット初期

そもそも、インターネット初期にはインターネットサービスの覇権企業など存在せず、
各大学や一部の企業・個人が自らサーバを構築して運用していた。

これは、中央集権から遠く離れたものだと考えられる。

現代のインターネットに必須な中央集権

現在のインターネットの運用に必要な企業・団体は多く存在する。

Tier 1プロバイダは各国との接続においてファイバーなどの維持を業務にしていたりするし、
ICANNなどはDNSの実運用上の必須団体といっても差支えないであろう。

ほかにも、RIPE NCCなどのIPアドレス・ASN管理団体も、
インターネットをインターネットとして運用するうえで必須の団体・企業といえるであろう。

Self-hostedとFOSS

もし中央集権的なインターネットから脱出したいなら、
Self-hostedとFOSSが重要なキーワードになるかもしれない。

Self-hostedとは自らサーバや環境を用意しサービスを提供することを指す。

FOSSは無料でオープンなソフトウェアを指し、
多くの場合オープンソースソフトウェアを指すワードである。

なぜFOSSがリストにいるのか

正直、Self-hostedだけあれば十分である。
しかし、そのサービスを長く使いたいのであれば、
特定の個人・法人に開発が一任されるプロプライエタリなソフトウェアではなく、
やる気さえあれば自分でプログラムをより良い方向へ持っていけるOSSを使うとよいだろう。

Self-hostedで中央集権から脱出する

Self-hostedなサービスで中央集権から脱出するには次の点を考える必要がある。

  • 2台以上のサーバを複数の国にまたいで設置する
  • 特定の国の予測不能なインターネット障害・遮断への対抗
  • ISP・IP管理団体の分散
  • gTLDを購入する
  • gTLDを取得することによって当該ドメインの管理団体がICANNのみになる
  • ここを一般ユーザを置いていかずに中央集権から分離させることはできなさそう?
  • できるだけSSL/TLSなどで暗号化する
  • 現代でサービスを運用する場合は必須です
  • できるだけバージョンが新しいものを利用しましょう
  • ソフトウェアはLTSもしくは最新のものを利用する
  • LTSが好ましい
  • 決して古いソフトウェアを使い続けないようにしましょう

ソフトウェアの例

メール

Modoboa

Modoboaはオールインワンのメールサーバソリューションである。

オープンソースであり、ある程度のセキュリティ設定もやってくれるらしい。

実際に運用する際にはPostfixなどでModoboaホストと接続できなくてもメールがDropしない仕組みを作るのは必須である。

オンラインファイルストレージ

Nextcloud

Nextcloudは何でもありのグループウェアである。

先に紹介したModoboaのメールをこのソフトウェアから閲覧することもできる。

また、カレンダーや連絡先も共有できるほか、チャットや通話も可能である。

連絡先・カレンダー

Nextcloud (別で紹介)

Nextcloudで紹介している。

チャット

Element

ElementはチャットソフトウェアとしてMatrixという公開されたプロトコルを使用しているソフトウェア。

詳しいわけではないので詳しい紹介はしないが、いかにもDecentralizedな感じの設計だと思う。

Mattermost

Mattermostは完全なオープンソース製品ではないが、
最低限チャットソフトウェアに欲しい機能は無料で提供してくれる。

UIはSlackに近く、Teamという概念でSlackのように複数ワークスペース作ることもでき、
個人・企業問わず便利なソフトウェアである。

通話

Jitsi

Jitsiはオープンソースのビデオ通話ソフト。

有名なWebで完結するビデオ通話ソフトウェアと同じように利用できる。

最後に

ここに書いてあるようなサービスを社内だけでも運用すると、
インターネットが発展するにあたってなぜ中央集権が必須となっていったのかよくわかる。

令和の世界でVAIO type Pを使う話

VAIO type P (VGN-P70H)という謎のUMPCを買ったので令和の世界でまともに使えるようにいろいろと頑張った話。

OS

さすがにWindows VistaやWindows 7を使うわけにはいかないのでWindows 10を入れるかLinuxを入れようと思います。

今回はDebian 11とXfceを入れました。

gihyo.jpの記事を見てめんどくさい作業が必要かとおびえていましたが、
標準のままでも特に問題なく動くようです。

Xfceを入れた理由

最初はLXDEを入れようとしましたが、ソフトウェアでrfkillが働き、
rfkillをインストールして毎回unblockしないといけないという謎の現象が起きたのでその次に軽そうなXfceを入れました。

PulseAudio問題

様々な記事においてDebian系OSでPulse Audioを使うと音飛びするという現象が報告されており、
私も同じ現象に悩まされたのでPulseAudioをアンインストールしました。

バックライト問題

Xfceの問題なのかVAIO type Pとの相性問題なのかバックライト系があまりいい感じに動きません。

今のところ
– しばらく放置して画面が暗転した後の操作でバックライトが設定値ではなく最大になる
– 再起動のたびにバックライト最大になる
– 定期的にXfceが再起動してバックライトが最大になる

これらの問題があります。
また、Xfce側ではどうやらバックライトの設定はもとのままというように認識しているらしく、
バックライトの明るさバーと実際の設定値が一致しません。

多分Xfce側がVAIO type Pに対応できてないだけだと思います。

Xfceが勝手に再起動する問題

その名の通りです。
セッションは引き継がれるのでそう見えてるだけかもしれませんが、
毎回画面ロック+バックライト最大になるのでつらいところです。

ハードウェアのアップグレード

SSD

私はまだ換装していませんが、SSD化(フラッシュ化)するのはかなりありだと思います。

そもそも、フラッシュ化しないと安心して持ち運びできないですよね。

バッテリ

VGP-VPL15という純正のLサイズバッテリがあります。

今いい感じの出品がないので買えませんが、近日中に手に入れたいですね。

用途

もともとRDPクライアント用として買いましたが、かなりいい感じです。

今のところWireGuardでVPNを張ってFreeRDPでリモート接続してます。
FreeRDPだとalsaを直接呼び出せるのでPulseAudio問題も回避できます。

USBシリアルケーブルとcuコマンドでシリアル通信で管理するタイプのルータの設定用マシンとしても使えます。

個人的には大満足です。

参考

  • https://lovely910.com/2019/12/30/%E4%BB%A4%E5%92%8C%E5%85%83%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E3%80%80manjaro-linux%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%97%E3%81%9Fvaio-typep%E3%81%AE%E3%81%9D/
  • https://gihyo.jp/admin/serial/01/ubuntu-recipe/0057?page=1

日本国内に蔓延る営業ワードとしてのIPoEを撲滅したい話

そもそも私もよく分かっていないが「IPoEは早い」などと洗脳されている友人を救うために書きました。

訂正等ありましたらここからお気軽にIssueやPull Request送ってください。

本来のIPoE

そもそも、NTT契約において「フレッツ・v6オプション(, 西)」
契約状態であれば、IPoEとしての接続が可能です。

IPoEとはInternet Protocol (NGNの場合はIPv6)をEthernet (フレッツの場合は光ファイバに変換される)に通すだけで、
これ単体ではIPv6のみが利用可能になります。
(また、NTT自体はプロバイダとしての役割を持っていないため、
インターネットに向けたIPv6通信にはVNEに契約し、VNE保有のIPv6アドレスを受け取れるようにする必要性があります)

________________________________
|          |      |            |
| Ethernet | IPv6 | Content    |
|__________|______|____________|

図にするとこんな感じ

これは、PPPoE時代から存在するシステムで、PPPoEはIPv4のみの対応(例外あり)であり、
これにIPv6を新たに提供するために導入されたものです(多分)。

しかし、これではIPv4が利用できません。

具体的に言うと、Yahoo! JAPANGitHubなどの
ほぼすべての Webサービスに接続できなくなります。

PPPoE

IPv4の接続性が無いと困りますから、IPv4の接続は別で確保する必要があります。

(正確にはPPPoEを利用した通信が先ですが、)PPPoEではIPv4接続性(一部はIPv6も対応)を提供します。
PPPoEはIPoE上で動作するのではなく、Ethernet(光回線)上でPPPの通信を行います。

PPPの通信はIPv4を内包します。

_____________________________________
|          |     |      |            |
| Ethernet | PPP | IPv4 | Content    |
|__________|_____|______|____________|

こんな感じ。

PPPoEが遅いと言われる理由

営業マンやブログはPPPoEが遅いと言います。

これは、PPPoEの通信にはプロバイダ側設備に行く前に一度NTT側設備を経由しますが、
その機材が昨今のトラヒック増加から処理が追いついていないことに起因します。

つまり、人口が少ない街などではPPPoEが遅いという現象は発生しません

営業マンが言うIPoE

都市圏では人口の増加によりNTT側設備が悲鳴を上げ、PPPoEでの通信に限界が出てきました。

そこで現れたのが営業マンがIPoEなどと読んでいる技術です。
実情的にはIPv4 over IPv6となります。

これは、これまでPPPoEを使っていたIPv4の通信をIPv6上に載せてインターネットに羽ばたかせます。

______________________________________
|          |      |      |            |
| Ethernet | IPv6 | IPv4 | Content    |
|__________|______|______|____________|

図にするとこんな感じ。相手に到達する際は送信時のEthernetとIPv6が取っ払われます。

技術的には
– MAP-E
– DS-ite

になり、代表的なサービスとして
v6プラス
OCN バーチャルコネクトサービス
Transix

などがあります。

また、MAP-Eでは1IPを複数契約で共有するので、IPv4アドレスを節約することが出来ます。

で、早いの?

結論を言えば、人口の多い都会においてPPPoEより早くなる場合があります。

しかし、人口の少ない田舎や、PPPoE利用者の少ない地域においてはPPPoEのほうが早くなるでしょう。

そもそも、IPoE方式では一部のサービスが利用できなくなる場合がありますので、
大前提としてPPPoEでの速度低下が著しい場合に試してみるのが賢い方法と言えます。

参考文献

Google Pixel Buds A-Seriesを買った話

初めてレビュー記事みたいなものを書きますが、
Pixel Buds A-Seriesを手に入れたので軽く使い勝手を書き連ねていきます。

もともとは乗り換え用

もともとはXperia Ear Duo
SoundSport Free wireless headphones
の乗り換え用で買ったものです。

ついでに、h.ear in Wirelessの代替として使えたらいいなという考えでした。

値段差が3分の1くらいのものなので正直期待はしていませんでしたが、
結論から言うと1万円でこれはかなりありな製品だったのではと思います。

音の感じ方

私の耳は音質の差を聞き取れるほど良い耳ではないので感じ方だけ。

SoundSport Freeや初代h.ear in Wirelessでは「音楽に包まれている」という感覚でしたが、
こちらは「音楽を聴いている」という感覚です。

悪いことではないですが音楽に浸りたいのであればBoseやSonyのお高めのイヤホンを買うべきでしょう。

雰囲気はXperia Ear Duoの音をもっといい感じにしたものです。

遮音性

ノイズキャンセリングや外音取り込みはついていません。

しかし、音として入ってくるのは大まかな音で会話内容はわからないレベルには遮音性はあります。

個人的には遮音性が高すぎるため、
会話がイヤホンを取り外さずにできるように外音取り込み機能はあったほうがよかったかなと思いました。
別に音質求めないので通話用のマイクで適当に実装してほしかったと思います。

通知・アシスタント機能

通知機能はとても便利です。

しかし、Xperia Earシリーズと違い、特定アプリからの通知が来た際にベルが鳴る形です。

この状態で本体のタッチパネルを長押しすると通知を読み上げてくれます。

音量の自動調整

音量調整機能ですが、Xperia Earの場合、相対的に現在の音量から調整してきますが、
Pixel Budsは絶対値で合わせているのではないかと思うほど音量を上げてきます。

Pixelとの連携

Pixelシリーズとの連携は最強です。

端末設定から本体の設定をできるので普通に便利です。

最後に

Androidユーザでしたら、普通にありな選択だと思いました。

個人的には片耳利用の際にどっちの耳でも聞けるのはよかったです。