NanoPi NEO2(arm64)用にFilebeatをビルド

「がとらぼ」ではホスト(サーバ)からの情報収集にcollectdを使ってたけど、collectdばかりでは面白くないのでElastic社の軽量エージェントBeatsも使ってみたいかなと。
Beatsはいろいろな機能別beatのシリーズ名みたいなものなのでBeatsという名前のアプリがあるわけではない。今回はログファイルを監視して追加されたログ(行)を送信するFilebeatをNanoPi NEO2 (arm64)用にビルドしてみたい。
ちなみにcollectdでログファイルを監視するならtailプラグインが似たようなもの。ただし、collectdでは基本的に(絶対的に?)文字列の値は送れなくて該当するログの行のカウントや数値だけなので文字列の値(ログそのもの)を送りたいならcollectdは外れるかな。

以下、コマンドの前(行頭)が $ のコマンドは一般ユーザーで実行、 # のコマンドは管理者として実行。(コマンドの前に sudoを付けるか su - でrootになってから実行)
また、この記事ではNanoPi NEO2のOSはarmbianのdebian stretch。違うディストリビューションでは標準で入っているパッケージがarmbianとは違うかもしれないので必要に応じて足す。

ビルド準備

BeatsはGo言語で書かれているということなので先ずはGoのインストール。

# apt-cache search golang
# apt install golang-go

apt-cache searchでGo言語のパッケージ名のキーワードとして golang を探す。表示されたリストにそれらしきパッケージ名が存在すればOK.
apt-get install でパッケージ名を指定してインストール。


~/.bashrc (追記)
export GOPATH=$HOME/.go

GOPATHを指定しておく。場所はどこでも良いので今回は自身のユーザーディレクトリ下の.goということにする。ディレクトリそのものは後で勝手に作られる(筈)。

Beatsの入手

$ go get github.com/elastic/beats
$ cd ~/.go/src/github.com/elastic/beats

$ cd filebeat
$ git checkout v5.6.7
(または最新v6.2.2ならgit checkout v6.2.2)

ビルドとインストール

上から引き続きで実行
$ GOARCH=arm64 go build
$ cp -p filebeat /usr/local/bin/
# cp filebeat.yml /etc/
# mkdir /var/log/filebeat
# mkdir /var/lib/filebeat

FreeBSDに慣れてるので/usr/local/bin にしたけどfilebeatの置き場所は好みで。下のサービス設定用ファイルのfilebeatのpathも置き場所に合わせる。

/lib/systemd/system/filebeat.service (新規)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[Unit]
Description=filebeat
Documentation=https://www.elastic.co/guide/en/beats/filebeat/5.6/index.html
Wants=userwork-online.target
After=network-online.target

[Service]
ExecStart=/usr/local/bin/filebeat -c /etc/filebeat.yml -path.data /var/lib/filebeat -path.logs /var/log/filebeat
Restart=always

[Install]
WantedBy=multi-user.target

設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
### 入力 ###
filebeat.prospectors:
    -
        input_type: log
        paths:
            - /var/log/*.log

### 出力 ###
#elasticsearhに送る場合 (送信先 ホスト192.168.0.2 ポート9200)
#output.elasticsearch:
#  hosts: ["192.168.0.2:9200"]

#logstashに送る場合 (送信先 ホスト192.168.0.2 ポート5043)
output.logstash:
  hosts: ["192.168.0.2:5043"]

テストなので/var/logにあるファイル名が.logで終わるファイル全部を監視する。

Filebeat起動

# systemctl enable filebeat.service   #←サービスを有効化 (最初の1回のみ)
# service filebeat start              #←サービスを開始

データ受信側 Logstashの設定

/usr/local/etc/logstash/test.conf (テスト用設定ファイル)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
input {
    beats {
        port => 5043
    }
}

output {
    stdout {
        codec => rubydebug
    }
}
テスト用の出力先は標準出力とする。

テスト用Logstashの実行

# /usr/local/logstash/bin/logstash  --path.data /tmp -f /usr/local/etc/logstash/test.conf

既に動いているLogstashと別にLogstashを実行するときは--path.data でどこか書き込み可能なディレクトリを指定する。
コマンド実行から暫くは反応が無いように見えるかもしれないけど待っていればlogstashのメッセージの後にfilebeatからのデータが表示されるようになる筈。
なお、ログの表示が停まった場合はログが追加されるようなこと(例えばNanoPi NEOにログインし直すなど)をすると新たなログの行が追加されてそれが表示される(筈)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
    "@timestamp" => 2018-02-27T11:55:04.563Z,
        "offset" => 77635,
      "@version" => "1",
    "input_type" => "log",
          "beat" => {
            "name" => "nanopineo2",
        "hostname" => "nanopineo2",
         "version" => "5.6.7"
    },
          "host" => "nanopineo2",
        "source" => "/var/log/auth.log",
       "message" => "Feb 27 11:55:01 localhost CRON[1753]: pam_unix(cron:session): session opened for user root by (uid=0)",
          "type" => "log",
          "tags" => [
        [0] "beats_input_codec_plain_applied"
    ]
}

こんな感じのが次々に出力される。

関連記事:

fail2ban (0.10系)をファイアウォールpfとの組み合わせで使う

fail2banはログを監視して設定したキーワード(ログイン認証に失敗など)の行を見つけたらログのその行に書かれたIPアドレスをファイアウォールに一定時間登録、期限が来たら解除するツール。インターネットにサーバーを公開していたら怪しいアクセスが大量にくるけど、キーワード部分の設定しだいではしつこいやつらの多くをBANすることができるかも。操作するのはファイアウォールに限らず他のコマンドも実行できる。1時間の間に同一のIPアドレスで認証失敗が3回あったらBAN(本来の用途)、ログに攻撃パターンが出現したらスクリプトを起動して攻撃し返して「攻性防壁を発動」っていう中二病的なことも設定次第でいろいろ。

で、そのfail2banが昨年夏頃にVer.0.9系からVer0.10系になってようやくIPv6対応になったのは良いんだけど、いろいろ変わった部分があって、Linuxとiptableの組み合わせではどうか知らないけどFreeBSDとpfの組み合わせで使っている人は困っているかも。というか、頭のカタい「がとらぼ」の中の人がしょっちゅう間違える。だからそのfail2ban v0.10系の設定備忘録。

v0.9系までの設定

/usr/locall/etc/fail2ban/jail.local
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[DEFAULT]
ignoreip = 127.0.0.1/8 192.168.0.0/24
bantime  = 3600    ←たしか秒指定のみだった
findtime  = 7200   ←たしか秒指定のみだった
maxretry = 2

[wordpress-auth]
enabled  = true
filter   = wordpress-auth
action   = pf
           sendmail-whois[name=wordpress-auth, dest=foobar@example.com, sender=fail2ban@example.com]
logpath  = /var/log/wordpress-access.log

そのままでも、おそらくv0.10系で読み込んだら起動はする。けど実際はエラーだらけ。

v0.10系の設定

/usr/locall/etc/fail2ban/jail.local
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1/128 192.168.0.0/24 2001:2c0:d800:6701::/64
bantime  = 12h30m
findtime  = 1d12h
maxretry = 2

destemail = foobar@example.com
sender = fail2ban@<fq-hostname>

banaction = pf
action_pf = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", actiontype=<allports>]
            %(mta)s-whois[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s"]

action = %(action_pf)s

[wordpress-auth]
enabled  = true
filter   = wordpress-auth
logpath  = /var/log/wordpress-access.log
#port = http,https

[hoge]
enabled  = true
filter   = hoge
logpath  = /var/log/hoge.log

[DEFAULT]セクションと各Jailセクション(上の例だと[wordpress-auth]や[hoge])に書くのは以前と同じくDEFAULTに書いたら全てのセクションで標準値扱い、Jailセクション側に書いたらそのセクションでは標準値を上書きなのでどちらに書かなくてはならないというのはない。
時間の指定は従来通り数値のみで秒扱い、その他1s (1秒), 1m (1分), 1h (1時間), 1d (1日), 1mo (1ヶ月), 1y (1年)のような単位付きの書き方もできる。

変数banactionでファイアウォールのpfを指定(action.d/pf.conf参照)。オプションとしてactiontype=<allports>を指定した。またはactiontype=<multiport>を指定するが、その場合は変数action_pfのbantimeの後ろあたりにport="%(port)s", を追加し、各セクションにもport= hogeを書くことになるかと。 (上の例ではコメントになっているport = http,https)
何で直でaction指定しないでaction_pf変数を使ってるのかはツッコまないで。

pfのアクション周りは全面刷新と言って良いくらいなのでaction.dディレクトリの中の.pf.confを確認しておいた方が良いかも。

フィルタに使うfailregexやignoreregexは変わってないように見えるのでfilter.d内に書くファイルはv0.9以前用がそのまま使えそう。

ファイアウォールpf周り

pf周りが完全に変わってしまっているのでv0.9系から更新する場合は要対応。

v0.9系までは以下な感じ。

/etc/pf.conf
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
ext_if = "em0"
table <private> const { 10/8, 172.16/12, 192.168/16 }
table <blacklist> persist file "/etc/pf_blacklist"
table <fail2ban> persist

set skip on lo0
scrub in all
scrub out on $ext_if all random-id
block all
block in  quick on $ext_if from { <private>, <blacklist>, <fail2ban> } to any
後略

上の例だと許可が無いので外部と通信できないけど後略の部分に許可ルールを書くとする。
と、いうことで、v0.9系までのfail2banではfail2banテーブルを作成してそのテーブルに含まれるIPアドレスからの通信を不許可にするルールを書いていた筈(4,10行目ね)。fail2banはそのfail2banテーブルにIPアドレスを追加・削除していた。

v0.10系ではこんな感じ。

/etc/pf.conf
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
ext_if = "em0"
table <private> const { 10/8, 172.16/12, 192.168/16 }
table <blacklist> persist file "/etc/pf_blacklist"

set skip on lo0
scrub in all
scrub out on $ext_if all random-id

anchor "f2b/*"

block all
block in  quick on $ext_if from {<private>, <blacklist>} to any
後略

9行目のアンカーがキモ。pfの設定に追加するのはこれだけ。別な書き方はマニュアル見てね。
アンカーは「IPアドレスの集合」ではなく「fail2banが作成した不許可ルール」がインクルードされると思えば良いかと。そのアンカーのルールは(fail2banが作るルール)はテーブルに含まれるIPアドレスからのパケットをドロップ。

つまり、アンカーにドロップルールが書かれているのでpf.confの独自ルールでドロップさせない(12行目ね)
fail2banが作ったf2b-hogeのテーブル名を使ったルールを他に作ってはダメということではない。

念の為に確認してみるとこんな感じ。

actiontype=<allports>指定の場合
# pfctl -a f2b/wordpress-auth -s rules
block drop quick proto tcp from <f2b-wordpress-auth> to any
# pfctl -a f2b/hoge -s rules
block drop quick proto tcp from <f2b-hoge> to any
actiontype=<multiport>指定の場合 (wordpress-authだけ)
# pfctl -a f2b/wordpress-auth -s rules
block drop quick proto tcp from  to any port = http
block drop quick proto tcp from  to any port = https

上のjail.local設定例の[wordpress-auth]のport指定のように2つのポートを指定すると2行できるみたい。 block drop quick proto tcp from to any port { www, https } みたいな書き方で良いのにねぇ。

f2b-wordpress-authやf2b-hogeはfail2banが自動作成するテーブルで、これにIPアドレスが入っている。
ルールとしてはテーブルに含まれるIPアドレスからの通信を不許可という簡単なもの。
そのテーブルを見てみる。

# pfctl -a "f2b/wordpress-auth" -t f2b-wordpress-auth -T show
   192.168.2.149
   192.168.2.150
# pfctl -a "f2b/hoge" -t f2b-hoge -T show
   192.168.2.151
   192.168.2.152

普通のテーブルの確認は pfctl -t テーブル名 -T show だけど、アンカーの場合は pfctl -a "アンカー名" -t テーブル名 -T show になるので間違いなく。

と、いうことで、アンカーの名前は「f2b/セクション名」でテーブルの名前は「f2b-セクション名」となる。これさえ憶えておけば間違わない筈。

誤登録IPアドレスの削除・誤削除IPアドレスの登録

基本的にはfail2ban-clientコマンドを使う。

# fail2ban-client unban --all    #全てのセクションに登録されている全IPアドレスを削除する場合
# fail2ban-client set セクション名 unbanip IPアドレス    #特定のIPアドレスを削除する場合
# fail2ban-client set セクション名 banip IPアドレス        #特定のIPアドレスをBANする場合

手動でpfctlを使ってIPアドレスを削除する場合

# pfctl -a "f2b/セクション名" -t f2b-セクション名 -T delete IPアドレス
1/1 addresses deleted.

v0.9系まではpfctl -t テーブル名 -T delete IPアドレスだったが、当然これもアンカー指定が必要。

fail2banの稼働ステータスを見る

# fail2ban-client status
Status
|- Number of jail:      13
`- Jail list:   wordpress-auth, hoge, hage,・・・ 


# fail2ban-client status wordpress-auth
Status for the jail: wordpress-auth
|- Filter
|  |- Currently failed: 33
|  |- Total failed:     2259
|  `- File list:        /var/log/wordpress-access.log
`- Actions
   |- Currently banned: 33
   |- Total banned:     98
   `- Banned IP list: 192.168.0.149
                         以下略
Up