#サーバーに入ってくる通信と、出ていく通信
ネットワークを使う攻撃は、向きで2つに分けられます。1つは、外からサーバーへ入ってくるものです(ポートを探す、開いているサービスに触る)。もう1つは、サーバーから外へ出ていくものです(乗っ取られたプログラムが C2 サーバーへつなぐ、データを持ち出す)。
Server Edition は、どちらの向きにも見張りを置いています。この講座で動かすのは、次の 5 つです。
| 向き | 機能 | 既定 | すること |
|---|---|---|---|
| 入る | 受信の既定拒否と SSH の締め出し防止 | オン | 許可したポートだけを通す |
| 入る | 外部公開ポートの監査 | 手動で実行 | 待ち受けているポートを一覧にして、危険なものを示す |
| 入る | 外部からのポートスキャンの検知と遮断 | オン | 多くのポートを探る送信元を見つけて、10 分遮断する |
| 出る | 悪性 IP への外向き通信の遮断 | オン | 一覧にある IP への通信を捨てる |
| 出る | DNS トンネリングの検知 | オン | DNS を使った持ち出しと、名前の総当たりの形を知らせる |
このうち遮断するのは、受信の既定拒否、スキャン元の遮断、悪性 IP への通信の遮断の 3 つです。DNS の見張りは、知らせるだけで、名前解決を止めません。
#練習の場所を作る
スキャンや接続は、別のアドレスから来ないと、本物に近い形になりません。そこで、同じマシンの中に、ネットワーク名前空間で小さな「別のマシン」を作ります。外のネットワークには、何も送りません。
変更を伴う操作です。練習用の VM で試してください。scanner という名前空間を作り、こちらを 10.200.0.1、相手役を 10.200.0.2 にします。
sudo ip netns add scanner
sudo ip link add veth-host type veth peer name veth-scan
sudo ip link set veth-scan netns scanner
sudo ip addr add 10.200.0.1/24 dev veth-host
sudo ip link set veth-host up
sudo ip netns exec scanner ip addr add 10.200.0.2/24 dev veth-scan
sudo ip netns exec scanner ip link set veth-scan up
sudo ip netns exec scanner ping -c1 -W1 10.200.0.164 bytes from 10.200.0.1: icmp_seq=1 ttl=64 time=0.045 ms
1 packets transmitted, 1 received, 0% packet loss, time 0mssudo ip netns exec scanner <コマンド> で、相手役のアドレスからコマンドを実行できます。ping が通るのは、受信の規則が ICMP を通すからです。
片付けるときは、名前空間の中で動かしたプログラムを止めてから消します。プログラムが残っていると、ip netns del のあとも veth-host が残りました。
sudo kill $(sudo ip netns pids scanner)
sudo ip netns del scanner#受信は、許可したポートだけ
Server Edition のファイアウォールは、受信を既定で拒否します。既定の設定で規則を見ると、通すのは、ssh_ports と allowed_ports の TCP、ICMP、このマシンが始めた通信への返事、ループバックでした。UDP は、allowed_udp_ports に書いた番号だけを通します。既定は allowed_ports=80,443、allowed_udp_ports は空です。
SSH のポート(ssh_ports)は、allowed_ports に書かなくても、いつも通ります。管理の入り口を、設定の書き忘れで閉じないためです。
開発用の Web サーバーを、全部のアドレス(0.0.0.0)で起動します。まず、外部公開ポートの監査 の一覧を見ます。
nohup python3 -m http.server 8080 --bind 0.0.0.0 >/dev/null 2>&1 &
sudo roamswitch ports=====================================================
🔍 外部公開・リスニングポート & 開発サーバー監査
=====================================================
• Port 8080 python3 PID: 1270 0.0.0.0 [注意] [DevServer] [ファイアウォールで外から遮断中]
↳ 0.0.0.0 バインド(RoamSwitch のファイアウォールで遮断中): 起動オプションでホストを 127.0.0.1 (localhost) に限定することを推奨します。
↳ フロントエンド・開発用Webサーバー露出: --host 127.0.0.1 で起動してください。
• Port 22 systemd (ssh.socket) PID: 1 0.0.0.0 (外部公開)[高リスク]
↳ 0.0.0.0 バインド(すべてのネットワークで待ち受け中): SSH の管理用のポート(ssh_ports)です。外すと締め出されるので、待ち受けはそのままにして、接続してよい相手を sudo roamswitch ssh-allow で限定できます。ports は、どのアドレスで待ち受けているかと、RoamSwitch の受信の規則が通すポートかを、あわせて見ます。0.0.0.0 は、すべてのアドレスで受け付ける、という意味です。8080 番は allowed_ports に無いため、「ファイアウォールで外から遮断中」と出ました。
sudo を付けると、root のプログラムの名前も出ます。この VM では、ssh.socket が sshd を起動するため、22 番の持ち主は systemd (ssh.socket) と出ます。
待ち受けを始めると、通知の履歴にも1件残りました。未知のポート公開の自動遮断 が、デーモンの起動のときには無かった待ち受けとして知らせたものです。
🚨 新しいプログラムがネットワーク向けに待ち受けを始めました: TCP 8080
python3(PID 1270)が TCP 8080 番で待ち受けています。デーモンの起動のときには無かった待ち受けです。
受け入れるポートの一覧(allowed_ports・allowed_udp_ports)に無いため、外からの新しい接続はファイアウォールが捨てています。
心当たりがなければ、このプログラムを調べてください(記録は sudo roamswitch port-anomaly)。では、相手役から本当に届くかを確かめます。
sudo ip netns exec scanner curl -s -m 3 -o /dev/null -w '%{http_code}\n' http://10.200.0.1:8080/ ; echo "exit $?"
sudo ip netns exec scanner nc -vz -w 3 10.200.0.1 22
curl -s -m 3 -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/000
exit 28
Connection to 10.200.0.1 22 port [tcp/ssh] succeeded!
2008080 番は、相手役からは時間切れ(curl の終了コード 28)です。受信の規則が捨てています。22 番は届き、同じマシンの中(127.0.0.1)からは 8080 番も使えます。ports の表示のとおりでした。
8080 番を外に開けたいときは、allowed_ports に足します。ここからは変更を伴う操作です。設定は保存しただけでは効かず、再起動で反映します。
sudo roamswitch server config set allowed_ports 80,443,8080
sudo ip netns exec scanner curl -s -m 3 -o /dev/null -w 'before restart %{http_code}\n' http://10.200.0.1:8080/
sudo roamswitch server restart
sudo nft list chain inet roamswitch_server input | grep dport
sudo ip netns exec scanner curl -s -m 3 -o /dev/null -w 'after restart %{http_code}\n' http://10.200.0.1:8080/
sudo roamswitch ports | grep -A1 "Port 8080" ✓ サーバー設定を更新・保存しました。 (allowed_ports = 80,443,8080)
反映するには: sudo systemctl restart roamswitch-server または sudo roamswitch server restart
before restart 000
🔄 roamswitch-server サービスを再起動中...
✓ roamswitch-server サービスを正常に再起動しました。
tcp dport { 22, 80, 443, 8080 } accept
after restart 200
• Port 8080 python3 PID: 1270 0.0.0.0 (外部公開)[高リスク] [DevServer]
↳ 0.0.0.0 バインド(すべてのネットワークで待ち受け中): 外から使わないなら、待ち受けを 127.0.0.1 に変更してください。外から使うなら、ファイアウォールで接続元を限ってください。開けたあとは、ports の 8080 番も「外部公開」「高リスク」に変わりました。
UDP も同じです。9999 番で受け取る小さなプログラムを動かし、相手役から1つずつ送ります。1つ目は allowed_udp_ports が空のとき、2つ目は 9999 を足して再起動したあとです。
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('0.0.0.0', 9999))
while True:
d, a = s.recvfrom(2048)
open('/tmp/udp.log', 'a').write(f"{a[0]} {d.decode().strip()}\n")nohup python3 /tmp/udprecv.py >/dev/null 2>&1 &
sudo ip netns exec scanner sh -c 'echo hello-udp-1 | socat - UDP-SENDTO:10.200.0.1:9999'
sudo roamswitch server config set allowed_udp_ports 9999
sudo roamswitch server restart
sudo ip netns exec scanner sh -c 'echo hello-udp-2 | socat - UDP-SENDTO:10.200.0.1:9999'
cat /tmp/udp.log10.200.0.2 hello-udp-2受け取りの記録には、2つ目だけが残りました。1つ目は、受信の規則が捨てています。
元に戻します。
sudo roamswitch server config set allowed_ports 80,443
sudo roamswitch server config set allowed_udp_ports ""
sudo roamswitch server restart- 開発用のサーバーを試すためだけに、
allowed_portsへ番号を足したままにする。使い終わったら外します。同じマシンの中だけで使うなら、127.0.0.1で起動すれば足ります ufwなど、ほかのファイアウォールの規則を同時に書き換えて、どれが効いているかわからなくする
#ポートスキャンを起こして、遮断を見る
攻撃の下調べでは、まず、どのポートが開いているかを探します。外部からのポートスキャンの検知と遮断 は、1つの送信元が、短い時間に多くの別々のポートへ接続を試みたら、スキャンとみなします。
既定は、300 秒(port_scan_detect_window_secs)のうちに 15 ポート(port_scan_detect_min_distinct_ports)です。見つけたら知らせ、port_scan_block_enabled=true(既定)なら、その送信元を 600 秒(port_scan_block_duration_secs)遮断します。
相手役から、このマシンの 1〜200 番を調べます。自分の VM の中だけで行います。
sudo ip netns exec scanner nmap -sS -Pn -n -p 1-200 --max-retries 0 -T4 10.200.0.1Not shown: 198 filtered tcp ports (no-response)
PORT STATE SERVICE
22/tcp open ssh
80/tcp closed http
Nmap done: 1 IP address (1 host up) scanned in 1.51 secondsfiltered は、受信の規則が黙って捨てたポートです。80 番が closed なのは、通す設定でも、待ち受けるプログラムがないからです。
判定は、カーネルの記録をおよそ 1 分ごとに読んで行います。少し待ってから、結果を見ます。
sudo roamswitch port-scan
sudo nft list set inet roamswitch_portscan blocked_ips
sudo ip netns exec scanner nc -vz -w 3 10.200.0.1 22 【検知されたインシデント】
🚨 [2026-11-12T01:28:11.745990572+00:00] [遮断済み 10m] 10.200.0.2 - 接続先ポート数: 201 (例: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
table inet roamswitch_portscan {
set blocked_ips {
type ipv4_addr
flags timeout
elements = { 10.200.0.2 timeout 10m expires 9m24s521ms }
}
}
nc: connect to 10.200.0.1 port 22 (tcp) timed out: Operation now in progressスキャンの前は届いた 22 番にも、相手役からは新しくつなげなくなりました。遮断は、期限つきの集合(blocked_ips)に入れて行います。期限(expires)が来ると、カーネルが自動で外します。
通知の履歴には、検知と遮断の2件が残ります。インシデントのタイムライン にも、1行で残ります。
sudo roamswitch notifications
sudo roamswitch timeline 2026-11-12T01:28:11.745766778+00:00
スキャン元IPを遮断: 10.200.0.2
ホスト: ubuntu (IP: 192.168.64.5)
遮断対象: 10.200.0.2
遮断時間: 10 分(自動的に解除されます)
時刻: 2026-11-12 01:28:11
2026-11-12T01:28:11.560763514+00:00
着信ポートスキャンを検知: 10.200.0.2
🔍 短時間に 201 件の異なるポートへの接続試行がありました。偵察行為(ポートスキャン)の可能性があります
ホスト: ubuntu (IP: 192.168.64.5)
送信元: 10.200.0.2
検知ポート例: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
時刻: 2026-11-12 01:28:11
2026-11-12T01:28:11.746055322+00:00 [Port Scan Guard] 対応中
着信ポートスキャン: 10.200.0.2 から短時間に 201 個の異なるポートへ接続の試み(例: 1, 2, 3, 4, 5, 6, 7, 8)。送信元を 10 分遮断
実施した対応: 送信元を自動遮断
2026-11-12T01:25:25.314494300+00:00 [FIM] 記録のみ
ログの改ざんの比較の基準を作り直した
実施した対応: 記録のみ時刻は UTC です(日本時間は 9 時間後の 10:28:11)。タイムラインの [FIM] の行は、デーモンを最初に起動したときの記録です。記録のみで、通知は出ません。
期限を待たずに外すときは、集合から消します。変更を伴う操作です。
sudo nft delete element inet roamswitch_portscan blocked_ips "{ 10.200.0.2 }"
sudo ip netns exec scanner nc -vz -w 3 10.200.0.1 22Connection to 10.200.0.1 22 port [tcp/ssh] succeeded!外したあと、1 分以上待っても、同じスキャンで遮断し直されることはありませんでした。続けて、10 ポート(1000〜1009 番)だけを調べても、新しい検知は出ませんでした。15 ポートに届かないからです。
スキャンの送信元は、偽ることができます。そこで、同じネットワークの送信元を遮断する前に、その相手が本当にいるかを確かめます。近隣表(ip neigh)に MAC が無ければ、ARP で問い合わせてから判断します。
相手役に、実在するアドレス 10.200.0.3 と、スキャンのあいだだけ使う 10.200.0.77 を足して、それぞれから調べます。10.200.0.77 は、判定より前に外します。偽った送信元と同じく、誰も ARP に答えない状態です。近隣表も、事前に空にします。
sudo ip netns exec scanner ip addr add 10.200.0.3/24 dev veth-scan
sudo ip netns exec scanner ip addr add 10.200.0.77/24 dev veth-scan
sudo ip neigh flush dev veth-host
sudo ip netns exec scanner nmap -sS -Pn -n -e veth-scan -S 10.200.0.3 -p 1-200 --max-retries 0 -T4 10.200.0.1
sudo ip netns exec scanner nmap -sS -Pn -n -e veth-scan -S 10.200.0.77 -p 1-200 --max-retries 0 -T4 10.200.0.1
sudo ip netns exec scanner ip addr del 10.200.0.77/24 dev veth-scan
sudo ip neigh flush dev veth-host
# 1 分あまり待ってから
sudo roamswitch port-scan | grep "10.200.0.[37]"
sudo nft list set inet roamswitch_portscan blocked_ips | grep elements
ip neigh show dev veth-host 🚨 [2026-11-12T01:31:12.018525406+00:00] [遮断済み 10m] 10.200.0.3 - 接続先ポート数: 200 (例: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
🚨 [2026-11-12T01:31:15.498924939+00:00] [検知のみ] 10.200.0.77 - 接続先ポート数: 200 (例: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
elements = { 10.200.0.3 timeout 10m expires 9m9s774ms }
10.200.0.3 lladdr 12:c2:5c:db:da:1c STALE
10.200.0.77 FAILED 10.200.0.3 は、近隣表を空にしてあっても、問い合わせに答えたので遮断しました。10.200.0.77 は答えが無く(FAILED)、偽装とみなして、検知だけにしました。遮断しなかったことと、その理由は、通知の履歴に1件で残ります。
2026-11-12T01:31:15.498638901+00:00
スキャン元を遮断しませんでした(送信元の偽装): 10.200.0.77
ホスト: ubuntu (IP: 192.168.64.5)
遮断しなかった送信元: 10.200.0.77
理由: 送信元のアドレスが偽装されている形です(このネットワークの中のアドレスですが、応答する機器がありません)。遮断すると、そのアドレスの本当の持ち主の通信を止めてしまいます。
時刻: 2026-11-12 01:31:15サービスのログ(sudo journalctl -u roamswitch-server)にも、「source looks forged」の行が残ります。
元に戻します。
sudo nft delete element inet roamswitch_portscan blocked_ips "{ 10.200.0.3 }"
sudo ip netns exec scanner ip addr del 10.200.0.3/24 dev veth-scan- 続ける(既定): ふつうの利用者が、数十のポートに次々つなぐことはありません。遮断は新しい接続だけで、すでに張っている接続と、このマシンが始めた通信への返事は止めません
- 知らせるだけにする(
port_scan_block_enabled=false、再起動で反映): 社内の監視や診断のツールが、決まってポートを広く調べる環境です。止めると、その監視が 10 分ずつ途切れます
送信元のアドレスは偽れます。そのため、ゲートウェイ、DNS サーバー、このマシン自身のアドレスは、スキャンに見えても遮断しません(コードと設定ファイルの注記で確認)。同じネットワークの送信元は、演習のとおり、ARP に答える相手がいるときだけ遮断します。
#悪性の IP へ出ていく通信を止める
サーバーが乗っ取られると、中のプログラムが攻撃者のサーバーへつなぎに行きます。悪性 IP への外向き通信の遮断 は、一覧にある IP への外向きの通信を捨てます。このマシン自身の通信(output)と、通り抜ける通信(forward、Docker のコンテナの外向きの通信)の両方です。
パッケージに入っている一覧(/usr/share/roamswitch/threatfeed/malicious_ips.txt)は、空です。アドレスは、運用者が入れます。1 つは、/var/lib/roamswitch/threatfeed/malicious_ips.txt に手で書く方法です。もう 1 つは、egress_ip_feed_urls に https の URL を書く方法で、公開されている一覧を、1 日 1 回、取得先から直接取り込みます(既定は空で、何も取得しません)。
変更を伴う操作です。相手役の名前空間で Web サーバーを動かし、つながることを確かめてから、そのアドレスを一覧に書きます。
sudo ip netns exec scanner sh -c 'nohup python3 -m http.server 8000 --bind 10.200.0.2 >/dev/null 2>&1 &'
curl -s -m 3 -o /dev/null -w 'before %{http_code}\n' http://10.200.0.2:8000/
sudo mkdir -p /var/lib/roamswitch/threatfeed
echo "10.200.0.2" | sudo tee /var/lib/roamswitch/threatfeed/malicious_ips.txtbefore 200
10.200.0.2デーモンは、一覧を 5 分ごとに読み直します。再起動は要りません。この例では、書いてから約 297 秒後に規則へ入りました。待ち時間は、5 分の周期のどこで書いたかで変わります。
sudo nft list chain inet roamswitch_egress_block output
curl -s -m 3 -o /dev/null -w 'after %{http_code}\n' http://10.200.0.2:8000/; echo "exit $?"table inet roamswitch_egress_block {
chain output {
type filter hook output priority mangle; policy accept;
ip daddr 10.200.0.2 limit rate 5/minute burst 5 packets log prefix "rs_egress_drop: "
ip daddr 10.200.0.2 drop
}
}
after 000
exit 281 分ほどで、通知の履歴に残ります。
2026-11-12T01:38:11.519381381+00:00
外部通信をブロック: 10.200.0.2
🛡️ Egress guardが既知の悪性IPへの外部通信を遮断しました
ホスト: ubuntu (IP: 192.168.64.5)
ブロック先: 10.200.0.2
この区間でのマッチ数: 5
Dockerコンテナ発の通信も対象に含みます。
時刻: 2026-11-12 01:38:11
通信したプロセスは特定できません(ファイアウォールのログには、プロセスの情報が含まれません)通知は、どの宛先に出ようとしたかを示します。どのプログラムかは示しません。
元に戻すには、書いたファイルを消します。次の読み直しで、一覧は空に戻ります。この例では、消してから約 213 秒で戻り、curl は 200 を返しました。戻るまでは、そのアドレスへの通信は、DNS の問い合わせも含めて捨てられます。
sudo rm /var/lib/roamswitch/threatfeed/malicious_ips.txt一覧の IP への通信は、このマシンからも、コンテナからも、すべて捨てられます。攻撃者が使っていたサーバーのアドレスは、あとで、無関係なサイトが使うことがあります。正当な相手を止めていたら、その行を消してください。
名前解決の段階で止める設定(dns_sinkhole_enabled)もあります。既定はオフです。設定ファイルの例の注記では、社内向けの DNS(スプリットホライズン)に頼るサーバーが壊れるため、としています。
#DNS を使った持ち出しと、名前の総当たり
DNS の問い合わせは、たいていのネットワークで外へ出られます。攻撃者はそこを使い、データを長い名前に埋めて送ります(DNS トンネリング)。また、存在するサブドメインを探すために、ありそうな名前を次々に問い合わせます。
DNS トンネリングの検知 は、このマシンが送る問い合わせと、受け取る応答を見て、次の 2 つの形を知らせます。
| 形 | 条件(既定) |
|---|---|
| トンネリング | 同じドメインへの不審な形の問い合わせが、60 秒に 10 件。不審な形は、40 文字を超えてでたらめさの高いラベル、または TXT・NULL の種類 |
| 名前の総当たり | 同じドメインの下の別々の名前が、60 秒に 40 件、すべて「存在しない」(NXDOMAIN) |
知らせるだけで、問い合わせは止めません。見張りが止まっていても、名前解決は遅れない作りです(コードで確認)。
相手役の名前空間に、どの名前にも「存在しない」と答える小さな DNS サーバーを置きます。問い合わせは相手役にしか届かず、外の DNS には出ません。名前には、例示用に予約された example.com と example.net を使います。
# 練習用の DNS: どの名前にも「存在しない」(NXDOMAIN) と答える
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('10.200.0.2', 53))
while True:
q, a = s.recvfrom(512)
# ID はそのまま、フラグは応答 + NXDOMAIN、質問をそのまま返す
r = q[:2] + b'\x81\x83' + q[4:6] + b'\x00\x00\x00\x00\x00\x00' + q[12:]
s.sendto(r, a)まず、データを埋めたような長い名前を 12 回問い合わせます。続けて、よくあるサブドメイン名を 40 個問い合わせます。
sudo ip netns exec scanner sh -c 'nohup python3 /tmp/fakedns.py >/dev/null 2>&1 &'
for i in $(seq 1 12); do
label=$(head -c 30 /dev/urandom | base32 | tr -d '=' | tr 'A-Z' 'a-z' | head -c 48)
dig +noedns +short +tries=1 +time=1 @10.200.0.2 "$label.exfil-lab.example.com" >/dev/null
done
for w in admin api app beta blog cdn ci cms dev docs ftp git grafana jenkins jira k8s ldap mail mx ns1 ns2 portal proxy shop smtp sso stage static status test vpn web webmail wiki www intranet backup db files login m monitor; do
dig +noedns +short +tries=1 +time=1 @10.200.0.2 "$w.example.net" >/dev/null
done
sudo roamswitch notifications 2026-11-12T01:42:40.148964324+00:00
サブドメインの総当たり探索の兆候を検知しました
🔍 このホストが、example.net の下にある別々の名前を 60秒以内に 40 件問い合わせ、応答はすべて NXDOMAIN(その名前は存在しない)でした。サブドメインを総当たりで探す動きに見られる形です
名前の例: admin.example.net, api.example.net, app.example.net, beta.example.net, blog.example.net
このホスト、またはこのホスト上のプログラムが、名前を探っています。ご自身で起動したセキュリティ診断ツールか、乗っ取られたプロセスによる下調べが、よくある原因です
確認するには sudo roamswitch events search --since 10m で、この時間帯に起動したプログラムを見てください(実行記録が有効な場合)
このガードが見るのは、このホストが受け取る UDP の DNS 応答だけです。DoH、DoT、TCP の応答、独立したネットワーク名前空間にあるコンテナからの問い合わせは見えません
ホスト: ubuntu (IP: 192.168.64.5)
時刻: 2026-11-12 01:42:40
問い合わせを送ったプロセスは特定できません(DNS の問い合わせの記録には、プロセスの情報が含まれません)
2026-11-12T01:42:35.736366447+00:00
DNSトンネリング/持ち出しの兆候を検知しました
🔍 短時間に 10 件の、ラベルが長く高エントロピー、またはTXT/NULLタイプの不審な形のDNSクエリを、このホスト自身が送信しました。DNSトンネリングツール(iodine/dnscat2等)によるC2通信やデータ持ち出しの可能性があります
対象ドメイン: example.com
内訳: TXT 0件 / NULL 0件 / 長尺高エントロピーラベル 10件
ホスト: ubuntu (IP: 192.168.64.5)
時刻: 2026-11-12 01:42:35
問い合わせを送ったプロセスは特定できません(DNS の問い合わせの記録には、プロセスの情報が含まれません)12 回送って、10 件目で知らせました。名前の総当たりも、40 件目で知らせています。どちらも、問い合わせから数秒で通知の履歴に入りました。通知は「どのドメインに」を示し、「どのプログラムが」は示しません。総当たりの通知は、その時間帯に起動したプログラムを sudo roamswitch events search --since 10m で見るよう案内します。
社内のドメインが、長くでたらめな名前をふつうに使うことがあります(自動で作るホスト名など)。そのときは、dns_tunnel_entropy_allowlist にそのドメインを書きます。変更を伴う操作です。再起動で反映します。
sudo roamswitch server config set dns_tunnel_entropy_allowlist example.com
sudo roamswitch server restart
count() { sudo roamswitch notifications --json | python3 -c 'import json,sys; print(len(json.load(sys.stdin)))'; }
before=$(count)
for i in $(seq 1 12); do
label=$(head -c 30 /dev/urandom | base32 | tr -d '=' | tr 'A-Z' 'a-z' | head -c 48)
dig +noedns +short +tries=1 +time=1 @10.200.0.2 "$label.exfil-lab.example.com" >/dev/null
done
echo "count before=$before after=$(count)" ✓ サーバー設定を更新・保存しました。 (dns_tunnel_entropy_allowlist = example.com)
反映するには: sudo systemctl restart roamswitch-server または sudo roamswitch server restart
count before=13 after=13送る前と後で、通知の件数は 13 件のまま増えませんでした。許可リストを空に戻して再起動すると、同じ 12 回の問い合わせで、件数が 1 つ増えました。許可リストは、長い名前の判定と、名前の総当たりの判定を外します。TXT・NULL の種類の問い合わせは、許可リストに入れても知らせます(コードで確認)。
元に戻します。
sudo roamswitch server config set dns_tunnel_entropy_allowlist ""
sudo roamswitch server restart#見えない部分
使い捨ての Ubuntu 24.04 の VM の中で、名前空間の別アドレスを使って確かめました。
- ポートの一覧が見る規則は、RoamSwitch のものだけです。
roamswitch portsは、待ち受けのアドレスと、RoamSwitch の受信の規則で判定します。手前のルーターやクラウドの規則は見ません。外から本当に届くかは、外から確かめます - ゆっくりしたスキャンと、ループバックのスキャン。300 秒に 15 ポートに届かないものは数えません。ループバック(
lo)から来た接続は、そもそも数えません(コードで確認) - 悪性 IP の一覧は、一覧にあるものだけです。同梱は空で、運用者が書いたアドレスと、
egress_ip_feed_urlsで指定した一覧のアドレスだけが対象です。一覧にない C2 サーバーへの通信は止まりません。どのプログラムが通信したかも、通知には出ません - DNS の見張りが見ないもの。DoH・DoT、TCP の応答、独立したネットワーク名前空間にあるコンテナの問い合わせは見えません(通知の文言とコードで確認)。名前を細かく分けて、60 秒に 10 件より遅く送る持ち出しも、数えません
- この講座で扱わなかったもの。接続先のネットワークに応じた保護の切り替え、ARP の偽装、Wi-Fi の診断などは、デスクトップのクライアント版の機能です。この講座は Server Edition の範囲です
roamswitch ports で、8080 番に「ファイアウォールで外から遮断中」と出ました。正しい受け取り方はどれですか
解説を見る
portsは、待ち受けのアドレスと、RoamSwitch の受信の規則をあわせて見ます。演習では、相手役からの curl が時間切れになり、allowed_portsに足して再起動すると届きました。手前のルーターなどの規則は見ないので、本当に届くかは外から確かめます。
外向きの遮断の一覧に、相手役の IP を足しました。いつ効きますか
解説を見る
演習では、ファイルを書いてから約 297 秒後に規則へ入りました。消したときも、次の読み直しで反映されます。急ぐときは、
sudo roamswitch server restartで、すぐに読み直せます。
#次に学ぶこと
- SSH への総当たりの遮断と、接続元の限定は、SSH の保護の設定 で扱います
- 検知を通知先や SIEM へ届ける設定は、通知と転送の設定 にあります
- 設定のすべての項目は、Linux Server の運用マニュアル にあります
2026-11-12に確認しました。対象は Linux 1.17.39 です。公開の apt の 1.17.39 を入れた使い捨ての Ubuntu 24.04 の VM で、全演習を上から順に実行し、日本語と英語(LANG=en_US.UTF-8)の出力を取り直しました。
コマンドの出力は、製品の版や環境によって変わります。違いが出たら、まず製品の版を確かめてください。