【2026年5月26日時点の情報です】
Tripwireは、サーバーの大事なファイルが、知らないうちに書き換えられていないかを確かめるソフトです。
ファイルの状態をデータベースに記録しておき、あとで比べることで、ファイルの追加・削除・変更を見つけます。不正アクセスでプログラムを書き換えられたときに、気づくきっかけになります。
このサーバーでは、毎日深夜に自動でチェックし、変更があったときだけroot宛てにメールで知らせています。root宛てのメールは、AlmaLinux 9 初期設定の記事でGmailに転送するようにしているので、スマホで確認できます。
手順は「CentOSで自宅サーバー構築」を参考にしました。
1. Tripwireをインストールする
Tripwireは、標準のリポジトリではなく、EPEL(追加パッケージのリポジトリ)にあります。先にEPELを使えるようにしてから、Tripwireを入れます。
[root@almalinux ~]# dnf -y install epel-release ※EPELリポジトリを使えるようにする
[root@almalinux ~]# dnf -y install tripwire ※Tripwireをインストール
[root@almalinux ~]# tripwire-setup-keyfiles ※Tripwireの初期設定
Enter the site keyfile passphrase: ※サイトパスフレーズを決めて入力
Verify the site keyfile passphrase: ※もう一度入力
Enter the local keyfile passphrase: ※ローカルパスフレーズを決めて入力
Verify the local keyfile passphrase: ※もう一度入力
Please enter your site passphrase: ※サイトパスフレーズを入力
Please enter your site passphrase: ※サイトパスフレーズを入力パスフレーズは2種類あります。サイトパスフレーズは設定やポリシーを変えるときに、ローカルパスフレーズはデータベースを作るときに使います。このあと何度も使うので、忘れないように保管しておきましょう。
【2026年11月の追記】作った鍵のファイル(site.key と ホスト名-local.key)は、だれでも読める形(-rw-r--r--)になっていました。鍵はパスフレーズで守られていますが、ほかのユーザーに写し取られると、パスフレーズを当てる試しを手元でいくらでもできてしまいます。root だけが読める形にしておきます。Tripwire は root で動くので、毎日の確かめには影響しません。
[root@almalinux ~]# ls -l /etc/tripwire/site.key /etc/tripwire/almalinux-local.key ※今の権限を見る
-rw-r--r-- 1 root root 931 11月 1 16:38 /etc/tripwire/almalinux-local.key
-rw-r--r-- 1 root root 931 11月 1 16:38 /etc/tripwire/site.key
[root@almalinux ~]# chmod 600 /etc/tripwire/site.key /etc/tripwire/almalinux-local.key ※rootだけが読み書きできる形にする
[root@almalinux ~]# ls -l /etc/tripwire/site.key /etc/tripwire/almalinux-local.key ※権限が変わったか確かめる
-rw------- 1 root root 931 11月 1 16:38 /etc/tripwire/almalinux-local.key
-rw------- 1 root root 931 11月 1 16:38 /etc/tripwire/site.key
[root@almalinux ~]# twadmin --print-cfgfile > /dev/null && echo "cfg OK" ※Tripwireが鍵を使って設定を読めるか
cfg OKls -l /etc/tripwire/site.key /etc/tripwire/almalinux-local.key:
2つの鍵のファイルの権限を見る。-rw-r--r--は、だれでも読める形chmod 600 …:
持ち主(root)だけが読み書きできる形にする。中身は変わらないtwadmin --print-cfgfile > /dev/null && echo "cfg OK":
Tripwire が site.key を使って設定のファイル(tw.cfg)を読めるか。読めれば「cfg OK」と出る
2. Tripwireを設定する
2-1. 設定ファイルを変更する
[root@almalinux ~]# vi /etc/tripwire/twcfg.txt ※Tripwireの設定ファイル(テキスト版)を編集
LOOSEDIRECTORYCHECKING =false
↓
LOOSEDIRECTORYCHECKING =true ※ファイルが変わったときに、入っているディレクトリの変更までは通知しない
REPORTLEVEL =3
↓
REPORTLEVEL =4 ※レポートを詳しくする2-2. ポリシーファイルを最適化する
ポリシーファイルは、「どのファイルをチェックするか」を決めるファイルです。初期状態のままだと、このサーバーにはないファイルもチェック対象に入っていて、エラーがたくさん出ます。そこで、存在しないファイルのチェックを無効にし、存在するファイルのチェックを有効にするPerlのスクリプトを作って、ポリシーファイルを整えます。
[root@almalinux ~]# vi /etc/tripwire/twpolmake.pl ※ポリシーファイル最適化スクリプトを作成
#!/usr/bin/perl
# Tripwire Policy File customize tool
# ----------------------------------------------------------------
# Copyright (C) 2003 Hiroaki Izumi
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# ----------------------------------------------------------------
# Usage:
# perl twpolmake.pl {Pol file}
# ----------------------------------------------------------------
#
$POLFILE=$ARGV[0];
open(POL,"$POLFILE") or die "open error: $POLFILE" ;
my($myhost,$thost) ;
my($sharp,$tpath,$cond) ;
my($INRULE) = 0 ;
while (<POL>) {
chomp;
if (($thost) = /^HOSTNAME\s*=\s*(.*)\s*;/) {
$myhost = `hostname` ; chomp($myhost) ;
if ($thost ne $myhost) {
$_="HOSTNAME=\"$myhost\";" ;
}
}
elsif ( /^{/ ) {
$INRULE=1 ;
}
elsif ( /^}/ ) {
$INRULE=0 ;
}
elsif ($INRULE == 1 and ($sharp,$tpath,$cond) = /^(\s*\#?\s*)(\/\S+)\b(\s+->\s+.+)$/) {
$ret = ($sharp =~ s/\#//g) ;
if ($tpath eq '/sbin/e2fsadm' ) {
$cond =~ s/;\s+(tune2fs.*)$/; \#$1/ ;
}
if (! -s $tpath) {
$_ = "$sharp#$tpath$cond" if ($ret == 0) ;
}
else {
$_ = "$sharp$tpath$cond" ;
}
}
print "$_\n" ;
}
close(POL) ;スクリプトを使ってポリシーファイルを整え、暗号署名版のポリシーファイルを作ります。
[root@almalinux ~]# perl /etc/tripwire/twpolmake.pl /etc/tripwire/twpol.txt > /etc/tripwire/twpol.txt.new ※ポリシーファイルを最適化
[root@almalinux ~]# echo ! "/var/lib/tripwire/`hostname`.twd ;" >> /etc/tripwire/twpol.txt.new ※Tripwireのデータベース自体はチェックしない
[root@almalinux ~]# echo ! "/tmp/tripwire.log ;" >> /etc/tripwire/twpol.txt.new ※Tripwireのログはチェックしない(後で作る定期実行のスクリプトで使う)
[root@almalinux ~]# twadmin -m P -c /etc/tripwire/tw.cfg -p /etc/tripwire/tw.pol -S /etc/tripwire/site.key /etc/tripwire/twpol.txt.new ※最適化したポリシーから、暗号署名版のポリシーファイルを作成
Please enter your site passphrase: ※サイトパスフレーズを入力
Wrote policy file: /etc/tripwire/tw.pol
[root@almalinux ~]# rm -f /etc/tripwire/twpol.txt* ※テキスト版のポリシーファイルは削除(中身を見られないようにするため)テキスト版のポリシーファイルが必要になったときは、次のコマンドで戻せます。
[root@almalinux ~]# twadmin -m p -c /etc/tripwire/tw.cfg -p /etc/tripwire/tw.pol -S /etc/tripwire/site.key > /etc/tripwire/twpol.txt2-3. データベースを作る
今のファイルの状態を、データベースに記録します。この記録と比べて、変更を見つけます。
[root@almalinux ~]# tripwire -m i -s -c /etc/tripwire/tw.cfg ※Tripwireのデータベースを作成
Please enter your local passphrase: ※ローカルパスフレーズを入力3. 動きを確かめる
まず、そのままチェックを実行します。
[root@almalinux ~]# tripwire -m c -s -c /etc/tripwire/tw.cfg ※Tripwireのチェックを実行
Open Source Tripwire(R) 2.4.3.7 Integrity Check Report
(途中省略)
* Tripwire Data Files 100 1 0 0
(途中省略)
Total objects scanned: 38977
Total violations found: 1
(途中省略)
Added:
"/var/lib/tripwire/almalinux.twd.bak"ここでは、Tripwire自身が作ったデータベースのバックアップ(.twd.bak)が1件検知されています。これは問題ありません。
次に、テスト用のファイルを作って、きちんと検知されるか確かめます。
[root@almalinux ~]# echo test > test.txt ※テスト用のファイルを作成
[root@almalinux ~]# tripwire -m c -s -c /etc/tripwire/tw.cfg ※もう一度チェックを実行
(途中省略)
* Root config files 100 1 0 0 ← ファイルの追加を1件検知した
(途中省略)
Total violations found: 1 ← 1件の変更を検知した
(途中省略)
Rule Name: Root config files (/root)
Added:
"/root/test.txt" ← 追加されたファイル
[root@almalinux ~]# twprint -m r --report-level 1 -c /etc/tripwire/tw.cfg -r /var/lib/tripwire/report/almalinux-20260526-104317.twr ※チェック結果の要約を表示
Note: Report is not encrypted.
Added: "/root/test.txt" ※/root/test.txtの追加を検知した
[root@almalinux ~]# rm -f test.txt ※テスト用のファイルを削除(後始末)レポートのファイル名(almalinux-20260526-104317.twr)は、「ホスト名-日付-時刻」になるので、/var/lib/tripwire/report/ の中を ls で確かめてから指定してください。
4. 毎日自動でチェックする
毎日深夜3時に自動でチェックして、dnf の更新などで説明できない変更があったときだけroot宛てにメールで知らせるスクリプトを作ります。チェックが終わったらデータベースを作り直すので、「前の日から変わったファイル」だけが通知されます。
[root@almalinux ~]# dnf -y install tmpwatch ※古いファイルを消すツールをインストール
[root@almalinux ~]# vi /usr/local/sbin/tripwire-filter ※説明できない変化だけを取り出すスクリプトを作成(2026年11月に追加)
#!/bin/bash
# Tripwire の報告から、dnf の更新などで説明できない変化だけを出す。
# 使い方:tripwire-filter 報告ファイル.twr
# 終わりの番号:0 = 全部説明できた、1 = 説明できない変化がある、2 = 報告を読めなかった
set -u
R="$1"
W=$(mktemp -d); trap 'rm -rf "$W"' EXIT
/usr/sbin/twprint -m r -c /etc/tripwire/tw.cfg --twrfile "$R" -t 1 2>/dev/null \
| grep -oE '^(Added|Modified|Removed):[[:space:]]+"[^"]+"' \
| sed -E 's/:[[:space:]]+"/\t/; s/"$//' > "$W/all.tsv"
TOTAL=$(wc -l < "$W/all.tsv")
if [ "$TOTAL" -eq 0 ]; then echo "Tripwire の報告を読めなかった:$R"; exit 2; fi
grep -v $'\t/var/log/' "$W/all.tsv" > "$W/c.tsv" || true
awk -F'\t' '$1!="Removed"{print $2}' "$W/c.tsv" | while read -r f; do [ -d "$f" ] || echo "$f"; done | sort -u > "$W/files"
rpm -qal 2>/dev/null | sort -u > "$W/rpmfiles"
rpm -Va 2>/dev/null | awk '{print $NF}' | sort -u > "$W/mismatch"
comm -23 "$W/files" "$W/rpmfiles" | sed 's/^/[パッケージ外] /' > "$W/out"
comm -12 "$W/files" "$W/mismatch" | sed 's/^/[パッケージと違う] /' >> "$W/out"
PREV=$(ls -t /var/lib/tripwire/report/*.twr | grep -A1 -xF "$R" | sed -n 2p)
PREVT=$( [ -n "$PREV" ] && stat -c %Y "$PREV" || echo 0 )
LASTINST=$(rpm -qa --qf '%{INSTALLTIME}\n' | sort -n | tail -1)
if [ "$LASTINST" -le "$PREVT" ]; then
awk -F'\t' '$1=="Removed"{print "[消えた] "$2}' "$W/c.tsv" >> "$W/out"
else
awk -F'\t' '$1=="Removed" && $2 !~ /^\/usr\//{print "[消えた] "$2}' "$W/c.tsv" >> "$W/out"
fi
N=$(wc -l < "$W/out")
if [ "$N" -gt 0 ]; then
echo "Tripwire:説明できない変化 ${N}件(調べた変化 ${TOTAL}件のうち)"
cat "$W/out"
echo "くわしい報告:$R"
exit 1
fi
logger -t tripwire-filter "all ${TOTAL} changes explained ($R)"
exit 0
[root@almalinux ~]# chmod 755 /usr/local/sbin/tripwire-filter
[root@almalinux ~]# vi tripwire.sh ※定期実行のスクリプトを作成
#!/bin/bash
# 最初からある定期実行の設定を削除
rm -f /etc/cron.daily/tripwire-check
# パスフレーズ(長いでたらめなものにする)
LOCALPASS=xxxxxxxx # ローカルパスフレーズ
SITEPASS=xxxxxxxx # サイトパスフレーズ
TRIPWIRE=/usr/sbin/tripwire
TWADMIN=/usr/sbin/twadmin
TWPRINT=/usr/sbin/twprint
cd /etc/tripwire
# チェックを実行
# ※dnf の更新などで説明できない変化があったときだけ、root宛てに短くメールする
rm -f /var/lib/tripwire/report/`hostname`-`date +%Y%m%d`-*.twr
${TRIPWIRE} -m c -s -c tw.cfg > /tmp/tripwire.log
REPORT=$(ls -t /var/lib/tripwire/report/`hostname`-`date +%Y%m%d`-*.twr 2>/dev/null | head -1)
VIOL=$(grep "Total violations found" /tmp/tripwire.log | awk '{print $4}')
if [ -z "$REPORT" ] || [ -z "$VIOL" ]; then
printf 'Subject: Tripwire ERROR on %s\nContent-Type: text/plain; charset=UTF-8\n\nTripwire の調べが終わらなかったか、報告が見つからない\n' "`hostname`" | /usr/sbin/sendmail root
elif [ "$VIOL" -ne 0 ]; then
/usr/local/sbin/tripwire-filter "$REPORT" > /tmp/tripwire-filter.txt 2>&1
if [ $? -ne 0 ]; then
{ printf 'Subject: Tripwire unexplained changes on %s\nContent-Type: text/plain; charset=UTF-8\n\n' "`hostname`"; cat /tmp/tripwire-filter.txt; } | /usr/sbin/sendmail root
fi
fi
# 古いチェック結果を削除(過去90日分を残す)
tmpwatch -m 2160 /var/lib/tripwire/report
# ポリシーファイルを最新にする
${TWADMIN} -m p -c tw.cfg -p tw.pol -S site.key > twpol.txt
perl twpolmake.pl twpol.txt > twpol.txt.new
${TWADMIN} -m P -c tw.cfg -p tw.pol -S site.key -Q $SITEPASS twpol.txt.new > /dev/null
rm -f twpol.txt* *.bak
# データベースを作り直す
rm -f /var/lib/tripwire/*.twd*
${TRIPWIRE} -m i -s -c tw.cfg -P $LOCALPASS
[root@almalinux ~]# chmod 700 tripwire.sh ※rootだけが読めて、実行できるようにする
[root@almalinux ~]# echo "0 3 * * * root /root/tripwire.sh" > /etc/cron.d/tripwire ※毎日3時に実行する/usr/local/sbin/tripwire-filter:
報告から、記録のファイル(/var/log)と、パッケージの記録(rpm -Va)のとおりに更新されたファイルを外し、残った「説明できない変化」だけを出すスクリプト。何も残らなければ黙るREPORT=…・VIOL=…:
今日の報告のファイルの名前と、変化の数を取る。どちらかが取れなければ、エラーのメールを出す/usr/local/sbin/tripwire-filter "$REPORT" …; if [ $? -ne 0 ]:
変化があったら判断のスクリプトを動かし、説明できない変化があったときだけ、その短い結果をメールで送るprintf 'Subject: …\nContent-Type: text/plain; charset=UTF-8…' | /usr/sbin/sendmail root:
件名と文字コードを付けて送る。本文が日本語なので、文字化けしないように UTF-8 を付ける
スクリプトにはパスフレーズをそのまま書くので、必ず chmod 700 で、rootだけが読めるようにしておきます。
tmpwatchがインストールできない場合は、スクリプトの tmpwatch の行を、次の行に置き換えても同じように動きます。
find /var/lib/tripwire/report -name "*.twr" -mtime +90 -delete(2026年11月に直しました)はじめは、変化が1つでもあれば報告を丸ごとメールする形にしていました。ところが、毎朝の自動アップデート(dnf-automatic)で更新されたファイルが毎日数千件の変化として届き、読み流すしかなくなっていました。そこで、上のように、パッケージの記録のとおりに更新されたファイルなどを外して、説明できない変化があるときだけ短いメールが来る形にしました。あわせて、見張る場所を広げ、パスフレーズも長いでたらめなものに変えています。くわしくは「Tripwire の毎朝のメールを説明できない変化だけにした記事」にまとめています。
5. チェックしないファイルを追加する
ログのように、変わることが分かっているファイルやディレクトリは、チェック対象から外しておくと、余計な通知を減らせます。
[root@almalinux ~]# twadmin -m p -c /etc/tripwire/tw.cfg -p /etc/tripwire/tw.pol -S /etc/tripwire/site.key > /etc/tripwire/twpol.txt ※テキスト版のポリシーファイルを作成
[root@almalinux ~]# echo '!/var/log/sa ;' >> /etc/tripwire/twpol.txt ※例:ディレクトリ /var/log/sa をチェック対象外にする
[root@almalinux ~]# echo '!/etc/sysconfig/iptables ;' >> /etc/tripwire/twpol.txt ※例:ファイル /etc/sysconfig/iptables をチェック対象外にする
[root@almalinux ~]# twadmin -m P -c /etc/tripwire/tw.cfg -p /etc/tripwire/tw.pol -S /etc/tripwire/site.key /etc/tripwire/twpol.txt ※暗号署名版のポリシーファイルを作成
Please enter your site passphrase: ※サイトパスフレーズを入力
Wrote policy file: /etc/tripwire/tw.pol
[root@almalinux ~]# rm -f /etc/tripwire/twpol.txt /etc/tripwire/tw.pol.bak ※テキスト版とバックアップを削除
[root@almalinux ~]# rm -f /var/lib/tripwire/*.twd* ; tripwire -m i -s -c /etc/tripwire/tw.cfg ※データベースを作り直す
Please enter your local passphrase: ※ローカルパスフレーズを入力まとめ
Tripwireを入れて、毎日自動でファイルの変更をチェックし、変更があったときだけメールで知らせるようにしました。SELinuxやファイアウォールを止めているぶん、こうした検知の仕組みで安全性を補っています。
次は、不正なプログラム(rootkit)を探すrkHunterを入れます。手順はrkHunterの記事で紹介しています。



コメント