このブログは僕が yuuk1/shawk を動かしてみただけのブログで、技術的に得られる情報は少ないです。もしなにかを求められてきた方は、こちらの動画でなにかを得てください。
ということでやっていきましょう。上記のソフトウェアは下記の資料の実装体です。
僕のモチベーションとしてはペパボのサーバ間ネットワークをゼロトラストネットワークを前提として再構築する際に、既存のサーバ間がどのように通信しているのかを洗い出すためであったり、不正な通信の検知をできないかというちょっともとの研究とはそれた使い方かもしれません。
自分で使うとなると、僕の背景からはeBPFを利用するにはカーネルのバージョンアップを途方も無い台数実行必要が生まれるため、そのときはカーネルモジュールでの実装やauditdでの実装をコントリビュートする必要があるだろうなと思ったりもした。
そして、どうせブログ書くからrpm/debパッケージ作ったり、docker-compose.ymlでも書くかと思ってたいのですが、それもすでにあったので動かすだけでした。
まずはバイナリ作っていきましょう。
% make all
ほいで、docker-composeあるんで使っていきます。
% docker-compose up
shawk_db_1 is up-to-date
Starting shawk_agent_1 ... error
ERROR: for shawk_agent_1 Cannot start service agent: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"/go/bin/shawk\": stat /go/bin/shawk: no such file or directory": unknown
ERROR: for agent Cannot start service agent: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"/go/bin/shawk\": stat /go/bin/shawk: no such file or directory": unknown
ERROR: Encountered errors while bringing up the project.
あー、これdocker-composeは別途buildしろってことか。
% docker-compose build
db uses an image, skipping
Building agent
Step 1/3 : FROM golang:1.14.2
---> 2421885b04da
Step 2/3 : ENV PKG github.com/yuuki/shawk
---> Using cache
---> eff5000775c7
Step 3/3 : WORKDIR /go/src/$PKG
---> Using cache
---> 141e5f1d2e8f
Successfully built 141e5f1d2e8f
Successfully tagged shawk_agent:latest
% docker-compose up
shawk_db_1 is up-to-date
Starting shawk_agent_1 ... error
ERROR: for shawk_agent_1 Cannot start service agent: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"/go/bin/shawk\": stat /go/bin/shawk: no such file or directory": unknown
ERROR: for agent Cannot start service agent: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"/go/bin/shawk\": stat /go/bin/shawk: no such file or directory": unknown
ERROR: Encountered errors while bringing up the project.
あかんな。これbuildしたバイナリもっていかないかん。
volumes:
- ./shawk:/go/bin/shawk
雑に追加。
% docker-compose up
shawk_db_1 is up-to-date
Recreating shawk_agent_1 ... done
Attaching to shawk_db_1, shawk_agent_1
db_1 | Error: Database is uninitialized and superuser password is not specified.
db_1 | You must specify POSTGRES_PASSWORD to a non-empty value for the
db_1 | superuser. For example, "-e POSTGRES_PASSWORD=password" on "docker run".
db_1 |
db_1 | You may also use "POSTGRES_HOST_AUTH_METHOD=trust" to allow all
db_1 | connections without a password. This is *not* recommended.
db_1 |
db_1 | See PostgreSQL documentation about "trust":
db_1 | https://www.postgresql.org/docs/current/auth-trust.html
d
fmfm.ということで、dbのパスワード追加したり、環境変数入れたり。
services:
agent:
build: .
depends_on:
- db
entrypoint: /go/bin/shawk probe
command: ["--dbhost", "db"]
volumes:
- ./shawk:/go/bin/shawk
environment:
- SHAWK_CMDB_URL=postgres://shawk:shawk@db:5432/shawk?sslmode=disable
db:
image: postgres:11.7
ports:
- 5432
environment:
- POSTGRES_USER=shawk
- POSTGRES_DB=shawk
- POSTGRES_PASSWORD=shawk
restart: always
user: postgres
volumes:
- ./postgres/init:/docker-entrypoint-initdb.d
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ttracer"]
interval: 3s
timeout: 3s
retries: 5
start_period: 3s
そうすると、
agent_1 | flag provided but not defined: -dbhost
agent_1 |
agent_1 | Usage: shawk probe [options]
agent_1 |
agent_1 | start agent for collecting flows and processes.
agent_1 |
agent_1 | Options:
agent_1 | --env
agent_1 | --once run once only if --mode='polling'
agent_1 | flag provided but not defined: -dbhost
shawk_agent_1 exited with code 11
引き数変わったっぽいのでdbhostを削ってと。。
(⎈ |nks-production:drone)[13:52:25] ~/src/github.com/yuuki/shawk (not-exist-task) <U>
% docker-compose up
Starting shawk_db_1 ... done
Starting shawk_agent_1 ... done
Attaching to shawk_db_1, shawk_agent_1
db_1 |
db_1 | PostgreSQL Database directory appears to contain a database; Skipping initialization
db_1 |
db_1 | 2020-05-09 04:52:37.680 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
db_1 | 2020-05-09 04:52:37.680 UTC [1] LOG: listening on IPv6 address "::", port 5432
db_1 | 2020-05-09 04:52:37.689 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db_1 | 2020-05-09 04:52:37.726 UTC [12] LOG: database system was interrupted; last known up at 2020-05-09 04:50:50 UTC
db_1 | 2020-05-09 04:52:38.001 UTC [12] LOG: database system was not properly shut down; automatic recovery in progress
db_1 | 2020-05-09 04:52:38.005 UTC [12] LOG: redo starts at 0/16517C0
db_1 | 2020-05-09 04:52:38.005 UTC [12] LOG: invalid record length at 0/16517F8: wanted 24, got 0
db_1 | 2020-05-09 04:52:38.005 UTC [12] LOG: redo done at 0/16517C0
db_1 | 2020-05-09 04:52:38.033 UTC [1] LOG: database system is ready to accept connections
agent_1 | 2020/05/09 04:52:38 INFO <command> --> Connecting postgres ...
agent_1 | 2020/05/09 04:52:38 INFO <command> Connected postgres
db_1 | 2020-05-09 04:52:40.725 UTC [26] FATAL: role "ttracer" does not exist
db_1 | 2020-05-09 04:52:43.874 UTC [33] FATAL: role "ttracer" does not exist
[kkkdb_1 | 2020-05-09 04:52:47.025 UTC [41] FATAL: role "ttracer" does not exist
db_1 | 2020-05-09 04:52:50.187 UTC [48] FATAL: role "ttracer" does not exist
db_1 | 2020-05-09 04:52:53.331 UTC [55] FATAL: role "ttracer" does not exist
ああ、上がったけどdbのヘルスチェックが前の名前のままだったから、shawkに変える。
ここまでで1PRなげた。
db_1 |
db_1 | PostgreSQL Database directory appears to contain a database; Skipping initialization
db_1 |
db_1 | 2020-05-09 04:53:37.694 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
db_1 | 2020-05-09 04:53:37.695 UTC [1] LOG: listening on IPv6 address "::", port 5432
db_1 | 2020-05-09 04:53:37.699 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db_1 | 2020-05-09 04:53:37.746 UTC [12] LOG: database system was shut down at 2020-05-09 04:53:32 UTC
db_1 | 2020-05-09 04:53:37.760 UTC [1] LOG: database system is ready to accept connections
agent_1 | 2020/05/09 04:53:38 INFO <command> --> Connecting postgres ...
agent_1 | 2020/05/09 04:53:38 INFO <command> Connected postgres
db_1 | 2020-05-09 04:54:08.426 UTC [19] ERROR: relation "processes" does not exist at character 16
db_1 | 2020-05-09 04:54:08.426 UTC [19] STATEMENT:
db_1 | INSERT INTO processes (ipv4, pgid, pname, updated)
db_1 | VALUES ($1, $2, $3, CURRENT_TIMESTAMP)
db_1 | ON CONFLICT (ipv4, pgid, pname)
db_1 | DO UPDATE SET updated=CURRENT_TIMESTAMP
db_1 | RETURNING process_id
db_1 |
agent_1 | 2020/05/09 04:54:08 ERROR <agent/polling> query error:
agent_1 | github.com/yuuki/shawk/db.(*DB).InsertOrUpdateHostFlows
agent_1 | /go/src/github.com/yuuki/shawk/db/db.go:189
なるほどなぁ、スキーマが初期化されてなさそう。
多分このあたりを実行しないといけない。
command: bash -c "/go/bin/shawk create-scheme && /go/bin/shawk probe"
ソフトウェアの性質上、docker-composeはシュッと試したいときに使うものだから雑にbashでやっつけた。
ホイで起動したから雑に試すためにdocker exec bin/bashしてnetcatいれちゃうぞ〜。
$ apt install netcat
$ nc -l -p 11111 # listenしておいて
$ nc localhost 11111 # 接続する
$ /go/bin/shawk look
ここで、接続情報出るんかなぁと思ってたけどそんなことなかった。
なんでやねーーんと思ってたら、
agent_1 | 2020/05/09 05:14:57 ERROR <agent/polling> readlink /proc/58/fd/0:
agent_1 | github.com/yuuki/shawk/probe/netlink/netutil.BuildUserEntries
agent_1 | /go/src/github.com/yuuki/shawk/probe/netlink/netutil/netutil_linux.go:349
agent_1 | - readlink /proc/58/fd/0: permission denied
なるほどね。でもこれコンテナのprocだから特権いらなさそうだけどな。fd0だから標準入力見ようとしてんのかな。
あらためて、lookをip指定で見たらみれた。
root@615b76a8b754:/go/src/github.com/yuuki/shawk# /go/bin/shawk look --ipv4 172.19.0.3
172.19.0.3:55562 ('', pgid=0)
└<-- 172.19.0.3:many ('nc', pgid=505)
172.19.0.3 ('', pgid=0)
└--> 172.19.0.2:5432 ('', pgid=0)
172.19.0.3 ('nc', pgid=505)
└--> 172.19.0.3:55562 ('', pgid=0)
root@615b76a8b754:/go/src/github.com/yuuki/shawk# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 05:12 ? 00:00:05 /go/bin/shawk probe
root 22 0 0 05:14 pts/0 00:00:00 /bin/bash
root 47 0 0 05:14 pts/1 00:00:00 /bin/bash
root 381 0 0 05:16 pts/2 00:00:00 /bin/bash
root 505 47 0 05:24 pts/1 00:00:00 nc -l -p 11111
root 507 381 0 05:24 pts/2 00:00:00 nc 172.19.0.3 11111
root 560 22 0 05:26 pts/0 00:00:00 ps -ef
root@615b76a8b754:/go/src/github.com/yuuki/shawk#
これ11111ポートの情報はでないんかな。情報の出し方的には 172.19.0.3:many
の場所が 172.19.0.3:11111
で良さそうだけどなんでやろか。
root@615b76a8b754:/go/src/github.com/yuuki/shawk# /go/bin/shawk look --ipv4 172.19.0.3
172.19.0.3:55562 ('', pgid=0)
└<-- 172.19.0.3:many ('nc', pgid=505)
172.19.0.3 ('', pgid=0)
└--> 172.19.0.2:5432 ('', pgid=0)
172.19.0.3 ('nc', pgid=507)
└--> 172.19.0.3:11111 ('', pgid=0)
root@615b76a8b754:/go/src/github.com/yuuki/shawk# /go/bin/shawk look --ipv4 172.19.0.3
172.19.0.3:55562 ('', pgid=0)
└<-- 172.19.0.3:many ('nc', pgid=505)
172.19.0.3 ('', pgid=0)
└--> 172.19.0.2:5432 ('', pgid=0)
172.19.0.3 ('nc', pgid=505)
└--> 172.19.0.3:55562 ('', pgid=0)
コネクション自体は繋ぎっぱなしで、何回か実行してると結果が変わるっぽい。これはなんかポーリング間隔によって得られる情報が違うからなんだろう。openしか取ってないとするとあり得るから、ストリーミングモードでやると多分ちゃんと取れそう。
最後に
一通り動かしてみて、PRもさっきマージされてました。yuukiくんも書いてるようにパフォーマンスとのトレードオフになる部分はあれど、僕が思ってる用途や他の用途にも使えそうだった。それこそグラフ図にするとホスト間の依存を図示することもできるだろうし、CMDBがあるから基本ソフトウェアとして使い手のアイディア次第で可能性のあるソフトウェアだと思った。