Elastic Stack

  • Elasticsearch, Logstash, Kibana, Beatsなどのあれこれ.

Elasticsearch

dump

Logstash

Plugins

Installation using logstash-plugin command

  • Example: logstash-output-slack
root@elk:/usr/share/logstash/bin# ./logstash-plugin install logstash-output-slack
Validating logstash-output-slack
Installing logstash-output-slack

flow

  • http://enog.jp/wp-content/uploads/2015/09/enog43_elk_0904.pdf
    • ASN, gio-ipはいれたい.
  • https://www.janog.gr.jp/meeting/janog39/application/files/7014/8481/0318/janog39-traffic-nishizuka-03.pdf

slack通知

if [dstip] and [dstip] !~ "(^127.0.0.1)|(^10.)|(^172.1[6-9].)|(^172.2[0-9].)|(^172.3[0-1].)|(^192.168.)|(^169.254.)" {

Tools

Common

install battle on ubuntu18.04

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
echo "deb https://artifacts.elastic.co/packages/5.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-5.x.list
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.4.0.deb
sha1sum elasticsearch-5.4.0.deb
sudo dpkg -i elasticsearch-5.4.0.deb
sudo vim /etc/elasticsearch/jvm.options
java -version
sudo apt install default-jre
sudo apt list --installed | grep jre
curl -XGET 'localhost:9200/?pretty'
sudo vim /etc/elasticsearch/elasticsearch.yml
sudo service elasticsearch start

elk memo misc

ELK Install Battle

sudo apt install openjdk-8-jdk apt-transport-https
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
echo "deb https://artifacts.elastic.co/packages/6.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-6.x.list
sudo apt-get update && sudo apt-get install elasticsearch
sudo vi /etc/elasticsearch/elasticsearch.yml
sudo service elasticsearch status
sudo service elasticsearch start
sudo service elasticsearch status
sudo service elasticsearch enable
curl "http://localhost:9200/"
sudo apt install kibana
sudo vi /etc/kibana/kibana.yml
sudo service kibana status
sudo service kibana start
sudo service kibana enable
curl http://localhost:5601/ -L
sudo apt install logstash
sudo vim /etc/systemd/system/logstash.service
sudo systemctl status logstash
sudo systemctl start logstash
sudo vim /etc/logstash/conf.d/syslog.conf
sudo vi /etc/elasticsearch/elasticsearch.yml
sudo systemctl start elasticsearch.service
sudo systemctl daemon-reload
sudo systemctl enable kibana
sudo systemctl start kibana
sudo systemctl start logstash
curl http://localhost:9200/applogs/_search?q=*
curl http://localhost:9200//_search?q=*
curl http://localhost:9200/syslog/_search?q=*
curl localhost:9200

kea-dhcpのallocログからouiを取得してベンダをフィールドに追加する

  • 前提
"message" => "INFO  [kea-dhcp4.leases] DHCP4_LEASE_ALLOC [hwtype=1 01:23:45:67:89:ab], cid=[01:01:23:45:67:89:ab], tid=0x11111111: lease 1.2.3.4 has been allocated"
  • keaのリースログとしてこれが流れてくる.
  • sample.conf
input {
  elasticsearch {
    hosts => "localhost"
    query => '{ <Queries> }'
  }
}

filter {
  grok {
    "match" => { "message" => '.*\[hwtype.* %{COMMONMAC:macaddr}]' } # COMMONMACはdefaultのgrok-patternsとして存在する
  }

  mutate {
    add_field => ["macaddr_prefix", "%{macaddr}"]
  }

  mutate {
    gsub=> ["macaddr_prefix", "^(.{8}).*", "\1" ]
  }
}

  translate {
    dictionary_path => "/etc/logstash/oui.yml" # `"xx:xx:xx": "vender_name"` がリストされたymlへのpath
    field      => "macaddr_prefix"
    destination => "oui"
    fallback => "N/A"
  }
}

output{
  stdout { codec => rubydebug }
}
  • elasticsearchの既存indexからリースログを引くクエリを指定してinputとしている.
  • kibana等で可視化したい場合はoutputを別indexとしてelasticsearchに投げることでkibanaでも扱えるようになる.
    • この手法をとるとouiフィールドがあるindexと無いindexでほぼ同様の情報が2つdupで保存されてしまうことに注意する.

概要

  • Ubuntu18.04に
  • Elasticsearch(7.7)まわりのdebパッケージを
  • aptレポジトリから引っ張ってきて
  • インストールして
  • Logstash(log insert) -> Elasticsearch(processiog) <-> Kibana(visualize)ができる ところまでを実施します.

基本的に下記を参照します

Elastic Stack Install Battle

Install PGP key

$ wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
OK

add repository to apt source list

$ echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-7.x.list
deb https://artifacts.elastic.co/packages/7.x/apt stable main

Install Elasticsearch

$ sudo apt update
$ sudo apt install elasticsearch
$ sudo apt install elasticsearch
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  elasticsearch
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 314 MB of archives.
After this operation, 527 MB of additional disk space will be used.
Get:1 https://artifacts.elastic.co/packages/7.x/apt stable/main amd64 elasticsearch amd64 7.7.0 [314 MB]
Fetched 314 MB in 5min 57s (881 kB/s)
Selecting previously unselected package elasticsearch.
(Reading database ... 116882 files and directories currently installed.)
Preparing to unpack .../elasticsearch_7.7.0_amd64.deb ...
Creating elasticsearch group... OK
Creating elasticsearch user... OK
Unpacking elasticsearch (7.7.0) ...
Setting up elasticsearch (7.7.0) ...
Created elasticsearch keystore in /etc/elasticsearch/elasticsearch.keystore
Processing triggers for ureadahead (0.100.0-21) ...
Processing triggers for systemd (237-3ubuntu10.40) ...

ここまででelasticsearch自体のインストール自体は完了.

  • ヒープサイズのconfig JVMで使わせるヒープサイズをチューンする.一般には物理メモリの約半分を割り当てればいいそう. ただし32GBらへんに圧縮オブジェクトポインタのしきい値があるらしく,だいたい26GB以下にしておけば安全そう.
  • ref: Setting the heap size | Elasticsearch Reference [7.7] | Elastic 今回は物理メモリとして16GB割り当てているので8GBにしておく.
$ sudo cat /etc/elasticsearch/jvm.options | head -30
## JVM configuration

################################################################
## IMPORTANT: JVM heap size
################################################################
##
## You should always set the min and max JVM heap
## size to the same value. For example, to set
## the heap to 4 GB, set:
##
## -Xms4g
## -Xmx4g
##
## See https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html
## for more information
##
################################################################

# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space

-Xms8g
-Xmx8g

################################################################
## Expert settings
################################################################
##
## All settings below this section are considered
## expert settings. Don't tamper with them unless
$ sudo vim /etc/elasticsearch/elasticsearch.yml
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
network.host: <bind_ip>
#
# Set a custom port for HTTP:
#
http.port: 9200
#
# For more information, consult the network module documentation.

脳死したければ network.host: "0.0.0.0"とか入れておけばいいと思う.v6なら network.host: "::0"とか?

  • 起動してみる. 構築したホスト上でcurl "http://localhost:9200/" を打つと実際にelasticsearchにアクセスすることができる.
$ sudo systemctl start elasticsearch.service
$ sudo systemctl enable elasticsearch.service
$ sudo systemctl status elasticsearch.service
● elasticsearch.service - Elasticsearch
   Loaded: loaded (/usr/lib/systemd/system/elasticsearch.service; disabled; vendor preset: enabled)
   Active: active (running) since Sat 2020-05-16 14:33:17 UTC; 1 day 13h ago
     Docs: https://www.elastic.co
 Main PID: 3301 (java)
    Tasks: 83 (limit: 4915)
   CGroup: /system.slice/elasticsearch.service
           ├─3301 /usr/share/elasticsearch/jdk/bin/java -Xshare:auto -Des.networkaddress.cache.ttl=60 -Des.networkadd
           └─3505 /usr/share/elasticsearch/modules/x-pack-ml/platform/linux-x86_64/bin/controller

May 16 14:33:01 elk01 systemd[1]: Starting Elasticsearch...
May 16 14:33:17 elk01 systemd[1]: Started Elasticsearch.

$ curl "http://localhost:9200/"
{
  "name" : "ela01",
  "cluster_name" : "elc01",
  "cluster_uuid" : "xxxxxxxxxxxxxxxxxxxxxx",
  "version" : {
    "number" : "7.7.0",
    "build_flavor" : "default",
    "build_type" : "deb",
    "build_hash" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "build_date" : "2020-05-12T02:01:37.602180Z",
    "build_snapshot" : false,
    "lucene_version" : "8.5.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
$ /usr/share/elasticsearch/jdk/bin/java --version
openjdk 13.0.2 2020-01-14
OpenJDK Runtime Environment AdoptOpenJDK (build 13.0.2+8)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 13.0.2+8, mixed mode, sharing)

debパッケージをdpkgでいれたりtarballで引っ張ってきて展開したjavaまでついてくるかは知らない. 前はaptでも別にjdk入れないといけなかった気がしたけど,もう忘れてしまった.少なくとも最近のaptからのinstallでは一緒についてくるらしい.

  • Elastic Support Matrix | Elasticsearch と思ったらこれのサポートはあくまでelasticsearchを動かすだけにすぎなかった.elasticsearch本体だけなら動くけどlogstashとかはこのjdk verでは動かない. javaまでのpathが通ってない(and JAVA_HOMEが適切に環境変数に設定されていないと)こんな感じでapt installでerrorを吐く.
$ sudo apt install logstash
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  logstash
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 167 MB of archives.
After this operation, 295 MB of additional disk space will be used.
Get:1 https://artifacts.elastic.co/packages/7.x/apt stable/main amd64 logstash all 1:7.7.0-1 [167 MB]
Fetched 167 MB in 4min 54s (569 kB/s)
Selecting previously unselected package logstash.
(Reading database ... 103575 files and directories currently installed.)
Preparing to unpack .../logstash_1%3a7.7.0-1_all.deb ...
Unpacking logstash (1:7.7.0-1) ...
Setting up logstash (1:7.7.0-1) ...
could not find java; set JAVA_HOME or ensure java is in PATH
chmod: cannot access '/etc/default/logstash': No such file or directory
dpkg: error processing package logstash (--configure):
 installed logstash package post-installation script subprocess returned error exit status 1

なのでやっぱりELK stackを構築するなら $ sudo apt install openjdk-8-jre するのが正解.最近のELKコンポーネントだとopenjdk-11でもいいっぽいけどまぁ好きなの使えばいい気がする.ただjdk9以降はaptとかでさくっと入らないっぽく見えるからめんどそう.

Install logstash and Kibana

$ java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (build 1.8.0_252-8u252-b09-1~18.04-b09)
OpenJDK 64-Bit Server VM (build 25.252-b09, mixed mode)

javaが入ってる(PATHが通る)ことを確認して

sudo apt install logstash
sudo apt install kibana

でさくっとはいる.javaへのPATHが通ってないと失敗するので注意.

  • kibanaのconfig
$ sudo vim /etc/kibana/kibana.yml
server.port: 5601
server.host: "<bind_ip>"
elasticsearch.hosts: ["http://localhost:9200"]

<bind_ip>には前述のとおりlistenするipを入れる.

  • logstashのconfig
$ sudo vim /etc/logstash/jvm.options
-Xms8g
-Xmx8g
  • 起動
$ sudo systemctl start logstash
$ sudo systemctl start kibana
$ sudo systemctl enable logstash
$ sudo systemctl enable kibana

$ sudo systemctl status logstash
● logstash.service - logstash
   Loaded: loaded (/etc/systemd/system/logstash.service; disabled; vendor preset: enabled)
   Active: active (running) since Sat 2020-05-16 15:33:30 UTC; 1 day 11h ago
 Main PID: 7282 (java)
    Tasks: 43 (limit: 4915)
   CGroup: /system.slice/logstash.service
           └─7282 /usr/bin/java -Xms4g -Xmx4g -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseC
...(snip)...

$ sudo systemctl status kibana
● kibana.service - Kibana
   Loaded: loaded (/etc/systemd/system/kibana.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2020-05-16 14:40:41 UTC; 1 day 12h ago
 Main PID: 4569 (node)
    Tasks: 11 (limit: 4915)
   CGroup: /system.slice/kibana.service
           └─4569 /usr/share/kibana/bin/../node/bin/node /usr/share/kibana/bin/../src/cli -c /etc/kibana/kibana.yml
...(snip)...

ex. syslog insert to elasticsearch via logstash

syslogをlogstash経由でelasticsearchにいれてkibanaでみるところまでをやってみる. まずはsyslog pluginをlogstash-pluginを使って入れる.

$ /usr/share/logstash/bin/logstash-plugin list syslog
logstash-filter-syslog_pri
logstash-input-syslog
$ /usr/share/logstash/bin/logstash-plugin install logstash-input-syslog
ERROR: File /usr/share/logstash/Gemfile does not exist or is not writable, aborting
$ sudo /usr/share/logstash/bin/logstash-plugin install logstash-input-syslog
Validating logstash-input-syslog
Installing logstash-input-syslog
Installation successful

次にlogstashのconfigを作っていく. 適当にsyslogを受ける例を書くとこんな感じ.

$ cat /etc/logstash/conf.d/01-syslog.conf
input {
  syslog {
      port => 10514
      type => "syslog"
  }
}

filter {
} # filter

output {
  if "syslog" in [type] {
    elasticsearch {
      hosts => ["localhost:9200"]
      index => "logstash-syslog"
   }
    # stdout { codec => rubydebug }
  }
}

ポート番号1024以下はpriviledgedなのでroot権限等がないとpermission deniedで弾かれる. rootで実行するのも一つの手ではあるが,下記などではport forward(redirect)する例が挙げられている. 今回は10514としてそのまま利用する.

configを書いたらlogstash をrestartする.logstashの嫌なところはこのconfigを変えたらrestartする必要があるところ. 前段にkafkaなどのqueueをいれたりするのがこのrestartによるデータ欠損回避手段のうちの一つかもしれない.

$ sudo systemctl restart logstash

さて,ここまででlogstash -> elasticsearch ->kibanaのパイプラインが完成した. 実際にlogを突っ込んで見る.

logger -n localhost -P 10514 -t mytest -p user.notice --rfc3164 "TEST LOG"

これで送られた"はず"である.

ここからはkibanaでみていこう. kibanaへはconfigした通り,デフォルトでは5601ポートでアクセスする. kibanaでデータを取り扱う上でまずindex-patternを作る必要がある. Management -> Index Managementでelasticsearch側に先程のsyslogのindexが作成されていることを確認. これがないとindex patternを作っても見れない.これがない場合elasticsearchに正常にinsertされていない可能性が高いのでまずはそのdebugをしよう. この画面ではlogstashのconfigでindexとして指定したlogstash-syslogが見えている.

../_images/elk01.png

elasticsearchにindexがあることが確認できたら,今度はkibana側のindex patternsを見る デフォルトだと何も登録されていないので,Create Index Patternを押す

../_images/elk02.png

するとelasticsearchのindexが候補で見えてくる.

../_images/elk03.png

index patternの定義をするので,textboxにindex patternの名前(ワイルドカード可)を入れて1つに絞る. ここではlogstash-syslogそのまま入れると一つに絞ることができるのでNext Stepが押せるようになる.

../_images/elk04.png

次にtime filter firldを指定する.ここではlogstashでつける@timestampをそのまま使う. これでCreate Index Patternを押す.

../_images/elk05.png

するとIndexがつくられて

../_images/elk06.png

Index Patternのできあがり.

../_images/elk07.png

discover画面に行って確認すると,無事先ほどのloggerコマンドで転送したログが見える.

../_images/elk08.png

ここまでで一通りELKスタックを用いてsyslogをkibanaで見えるようになった.

### まとめ

  • Ubuntu18.04にElastic Stack (ELK, Logstash, Elasticsearch, Kibana)をaptパッケージを用いて構築した
  • Logstash(log insert) -> Elasticsearch(processiog) <-> Kibana(visualize)のパイプラインにsyslogを投入しkibanaで観測した.

logstashにはこの他にも色々なpluginがあり,様々なデータをELKスタックを用いてデータ分析/可視化することができる . また,logstash以外にもelasticsearchへの出力機能を持ったコンポーネント(ex. fluentd)などが数多くあるので,それらとうまく組み合わせて柔軟な分析基盤の構成ができそうである.

個人的にはDHCPサーバのリースログからクライアントのMACアドレスのベンダコード(OUI)をもとにベンダをを可視化したり,xflow(sflow/netflow)を食わせてgeo-ipの緯度経度データとIPアドレスを突き合わせてどの国/regionとの通信が多いのかを可視化したりすることもやってみたが,なかなかおもしろい. flowデータをもとにすれば通信をポート番号ベースで可視化したりすることができ,特定ポート宛などのDDoSの検知や内部から外部への不正な大量トラフィック(マルウェア感染端末からのDNS Amp.など)の検出もできそうである.可視化で得られた異常なデータをクリックすることでそのデータの詳細なレコードもkibanaならすぐに見ることができてユーザ体験はとてもよい. 可視化することは人間に直感的にあらゆる物事を短時間で理解させることを手助けする大きな価値のある手法であると思うので,是非このような可視化/分析ツール活用していきたいものである.