最近のUbuntu Linuxはufw(User Fire Wall)でiptablesをサクッと管理できる。iptableはある一定の攻撃とかバーストしてきた物は遮断してログに出力する事ができる。ufwだと/var/log/ufw.logに出力されて…こんな感じで見れる。
Jan 15 06:54:07 xxxxxxxx kernel: [403471.687391] [UFW BLOCK] IN=eth0 OUT= MAC=02:AA:BB:CC:DD:EE:FF:GG:HH:II:JJ:KK:LL:00 SRC=94.179.145.26 DST=AAA.AAA.AAA.AAA LEN=40 TOS=0x00 PREC=0x00 TTL=239 ID=16411 PROTO=TCP SPT=9807 DPT=23231 WINDOW=8192 RES=0x00 SYN URGP=0 Jan 15 06:54:18 xxxxxxxx kernel: [403483.004926] [UFW BLOCK] IN=eth0 OUT= MAC=02:AA:BB:CC:DD:EE:FF:GG:HH:II:JJ:KK:LL:00 SRC=203.189.152.165 DST=AAA.AAA.AAA.AAA LEN=44 TOS=0x00 PREC=0x00 TTL=240 ID=15727 PROTO=TCP SPT=62986 DPT=23 WINDOW=14600 RES=0x00 SYN URGP=0 Jan 15 06:54:44 xxxxxxxx kernel: [403509.027416] [UFW BLOCK] IN=eth0 OUT= MAC=02:AA:BB:CC:DD:EE:FF:GG:HH:II:JJ:KK:LL:00 SRC=203.189.156.28 DST=AAA.AAA.AAA.AAA LEN=44 TOS=0x00 PREC=0x00 TTL=240 ID=4355 PROTO=TCP SPT=2541 DPT=23 WINDOW=14600 RES=0x00 SYN URGP=0
ufwの詳細ログについてはこちら。
一部割愛しているけど、まぁこんな感じ。折角、アタックしてきてくれているから、このlogginデータを使わないわけにはいけないよね…何か楽しいし(w)と思うのは自然な感じ。現実的にはアタックログを残しておく事は有用になる。例えば、サーバ負荷との関連、アタックの頻度・トレンド、攻撃元IPアドレスのブラックリスト化などなど。
というわけで、構成はこんな感じでkibanaで可視化することに。
[ufw.log]->[fluentd]->[elasticsearch]->[kibana]
まずは結果から…データは2017/01/14-17のとある1個のサーバに対して。こんな感じ。
1) attack logging count
15,290(3.53 attack/min)。
2) TCP/UDP attack
TCP: 12,728, UDP:2,562
まぁ…TCPですよねー感はする。
2) port/tcp, udp attack top 20
イマドキtelnetかよ(w)的なツッコミをしたくなる。
3) attack country unique ip top 20
China 1076 Viet Nam 367 United States 334 Brazil 294 Korea, Republic of 274 Turkey 251 India 214 Taiwan, Province of China 210 Mexico 207 Russian Federation 196 Iran, Islamic Republic of 134 Argentina 101 Romania 86 Italy 80 France 78 Ukraine 75 Thailand 74 Australia 64 Poland 60 Colombia 60
1位は断トツの中国。まぁこれはそうですね感はするけど、2位がUSを抜いてベトナムというのが何気にビリビリするものがある。あとはいっぱいIPアドレスのリストが取れて何か嬉しい(w)。
他にも攻撃してきたipをtracerouteして逆向きのIPアドレスの情報もロギングして取得している。例えばこんな感じに(超割愛しているw)
攻撃元 IP 101.204.212.118 Lon/Lat 30.6667, 104.067 国/街 China/Chengdu +-----+-----------------+---------+---------+---------------+-------------------+ | ttl | ip_addr | lon | lat |country_name| city_name | +-----+-----------------+---------+---------+---------------+-------------------+ | 1 | 133.208.191.134 | 139.692 | 35.6895 | Japan | Tokyo | | 2 | 62.115.63.101 | -87.65 | 41.85 | United States | Chicago | | 3 | 213.248.82.206 | 8.68417 | 50.1155 | Germany | Frankfurt am Main | | 4 | 219.158.25.29 | 116.397 | 39.9075 | China | Beijing | | 5 | 219.158.103.97 | 116.397 | 39.9075 | China | Beijing | | 6 | 219.158.110.222 | 116.397 | 39.9075 | China | Beijing | +-----+-----------------+---------+---------+---------------+-------------------+
この場合は、中国->ドイツ->アメリカ->日本といった経路っすね。近いのに地球の反対側を通ってきているね。遠方よりはるばるお疲れさまです。このデータはDBに突っ込んでおいて使えるようにしていたりもする。
■ 設定
1) UFW
このufwはめっちゃ簡単にiptablesを管理できるからサラッと使っていたりする。例えば…
# ufw status 状態: アクティブ To Action From -- ------ ---- 443 ALLOW Anywhere 80 ALLOW Anywhere 80 (v6) ALLOW Anywhere (v6) 443 (v6) ALLOW Anywhere (v6)
こんな感じで一覧でサクッと分かる。iptablesだと…標準だとこんな感じね。
# iptables -L Chain INPUT (policy DROP) target prot opt source destination ufw-before-logging-input all -- anywhere anywhere ufw-before-input all -- anywhere anywhere ufw-after-input all -- anywhere anywhere ufw-after-logging-input all -- anywhere anywhere ufw-reject-input all -- anywhere anywhere ufw-track-input all -- anywhere anywhere Chain FORWARD (policy DROP) target prot opt source destination ufw-before-logging-forward all -- anywhere anywhere ufw-before-forward all -- anywhere anywhere ufw-after-forward all -- anywhere anywhere ufw-after-logging-forward all -- anywhere anywhere ufw-reject-forward all -- anywhere anywhere ufw-track-forward all -- anywhere anywhere Chain OUTPUT (policy ACCEPT) target prot opt source destination ufw-before-logging-output all -- anywhere anywhere ufw-before-output all -- anywhere anywhere ufw-after-output all -- anywhere anywhere ufw-after-logging-output all -- anywhere anywhere ufw-reject-output all -- anywhere anywhere ufw-track-output all -- anywhere anywhere Chain ufw-after-forward (1 references) target prot opt source destination Chain ufw-after-input (1 references) target prot opt source destination ufw-skip-to-policy-input udp -- anywhere anywhere udp dpt:netbios-ns ufw-skip-to-policy-input udp -- anywhere anywhere udp dpt:netbios-dgm ufw-skip-to-policy-input tcp -- anywhere anywhere tcp dpt:netbios-ssn ufw-skip-to-policy-input tcp -- anywhere anywhere tcp dpt:microsoft-ds ufw-skip-to-policy-input udp -- anywhere anywhere udp dpt:bootps ufw-skip-to-policy-input udp -- anywhere anywhere udp dpt:bootpc ufw-skip-to-policy-input all -- anywhere anywhere ADDRTYPE match dst-type BROADCAST Chain ufw-after-logging-forward (1 references) target prot opt source destination LOG all -- anywhere anywhere limit: avg 3/min burst 10 LOG level warning prefix "[UFW BLOCK] " Chain ufw-after-logging-input (1 references) target prot opt source destination LOG all -- anywhere anywhere limit: avg 3/min burst 10 LOG level warning prefix "[UFW BLOCK] " Chain ufw-after-logging-output (1 references) target prot opt source destination Chain ufw-after-output (1 references) target prot opt source destination Chain ufw-before-forward (1 references) target prot opt source destination ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED ACCEPT icmp -- anywhere anywhere icmp destination-unreachable ACCEPT icmp -- anywhere anywhere icmp source-quench ACCEPT icmp -- anywhere anywhere icmp time-exceeded ACCEPT icmp -- anywhere anywhere icmp parameter-problem ACCEPT icmp -- anywhere anywhere icmp echo-request ufw-user-forward all -- anywhere anywhere Chain ufw-before-input (1 references) target prot opt source destination ACCEPT all -- anywhere anywhere ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED ufw-logging-deny all -- anywhere anywhere ctstate INVALID DROP all -- anywhere anywhere ctstate INVALID ACCEPT icmp -- anywhere anywhere icmp destination-unreachable ACCEPT icmp -- anywhere anywhere icmp source-quench ACCEPT icmp -- anywhere anywhere icmp time-exceeded ACCEPT icmp -- anywhere anywhere icmp parameter-problem ACCEPT icmp -- anywhere anywhere icmp echo-request ACCEPT udp -- anywhere anywhere udp spt:bootps dpt:bootpc ufw-not-local all -- anywhere anywhere ACCEPT udp -- anywhere 224.0.0.251 udp dpt:mdns ACCEPT udp -- anywhere 239.255.255.250 udp dpt:1900 ufw-user-input all -- anywhere anywhere Chain ufw-before-logging-forward (1 references) target prot opt source destination Chain ufw-before-logging-input (1 references) target prot opt source destination Chain ufw-before-logging-output (1 references) target prot opt source destination Chain ufw-before-output (1 references) target prot opt source destination ACCEPT all -- anywhere anywhere ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED ufw-user-output all -- anywhere anywhere Chain ufw-logging-allow (0 references) target prot opt source destination LOG all -- anywhere anywhere limit: avg 3/min burst 10 LOG level warning prefix "[UFW ALLOW] " Chain ufw-logging-deny (2 references) target prot opt source destination RETURN all -- anywhere anywhere ctstate INVALID limit: avg 3/min burst 10 LOG all -- anywhere anywhere limit: avg 3/min burst 10 LOG level warning prefix "[UFW BLOCK] " Chain ufw-not-local (1 references) target prot opt source destination RETURN all -- anywhere anywhere ADDRTYPE match dst-type LOCAL RETURN all -- anywhere anywhere ADDRTYPE match dst-type MULTICAST RETURN all -- anywhere anywhere ADDRTYPE match dst-type BROADCAST ufw-logging-deny all -- anywhere anywhere limit: avg 3/min burst 10 DROP all -- anywhere anywhere Chain ufw-reject-forward (1 references) target prot opt source destination Chain ufw-reject-input (1 references) target prot opt source destination Chain ufw-reject-output (1 references) target prot opt source destination Chain ufw-skip-to-policy-forward (0 references) target prot opt source destination DROP all -- anywhere anywhere Chain ufw-skip-to-policy-input (7 references) target prot opt source destination DROP all -- anywhere anywhere Chain ufw-skip-to-policy-output (0 references) target prot opt source destination ACCEPT all -- anywhere anywhere Chain ufw-track-forward (1 references) target prot opt source destination Chain ufw-track-input (1 references) target prot opt source destination Chain ufw-track-output (1 references) target prot opt source destination ACCEPT tcp -- anywhere anywhere ctstate NEW ACCEPT udp -- anywhere anywhere ctstate NEW Chain ufw-user-forward (1 references) target prot opt source destination Chain ufw-user-input (1 references) target prot opt source destination ACCEPT tcp -- anywhere anywhere tcp dpt:https ACCEPT udp -- anywhere anywhere udp dpt:https ACCEPT tcp -- anywhere anywhere tcp dpt:http ACCEPT udp -- anywhere anywhere udp dpt:http Chain ufw-user-limit (2 references) target prot opt source destination LOG all -- anywhere anywhere limit: avg 3/min burst 5 LOG level warning prefix "[UFW LIMIT BLOCK] " REJECT all -- anywhere anywhere reject-with icmp-port-unreachable Chain ufw-user-limit-accept (2 references) target prot opt source destination ACCEPT all -- anywhere anywhere Chain ufw-user-logging-forward (0 references) target prot opt source destination Chain ufw-user-logging-input (0 references) target prot opt source destination Chain ufw-user-logging-output (0 references) target prot opt source destination Chain ufw-user-output (1 references) target prot opt source destination
まぁ..iptablesはパッと見で意味不明っすね。ってことで、ufwは適宜設定しておく。
2) fluentdの設定
ノリでこんな感じ。ufwからは他にも色々と取れたりするから適宜取得しておく。ぶっちゃけ、これ書いて設定とか終わりな感はする。ufwで必要なログを取って、fluentdでelasticsearchに流す設定をするだけ。
<source> type tail time_key time format /(?<time>[^\]]*).*SRC=(?<src>[^ ]*).*PROTO=(?<proto>[^ ]*).*DPT=(?<dpt>[^ ]*).*/ time_format %b %d %H:%M:%S path /var/log/ufw.log pos_file /var/log/td-agent/ufw.pos tag ufw.combined </source> <match ufw.*> type elasticsearch host hogehoge.host port 9200 index_name ufw_log type_name ufw_log logstash_format true logstash_prefix ufw_access logstash_dateformat %Y%m </match>
3) elasticsearch/kibanaの設定
これはググればOK。突っ込んで見るだけ。
■ おわりに…
こういうデータを持っておいて可視化しておくと、攻撃元IPのブラックリスト化、攻撃の傾向/トレンドの把握とかで、まぁちょろっとは使えるでしょう。まぁ、あとはpub/sub系のに流して、ブラウザで攻撃があったら情報がリアルタイムで見れるようにしておくとかね。これ系のは何となくそれなりっぽい規模の会社に1個くらい、可視化しれ見れるよーにしておくと、何となく後々幸せになれるような気がちょっぴりする。
あとtracerouteをかけて、経路のデータ/IPアドレスを取得してDBにまるごと突っ込んで簡単に使えるようにもしている。何となくDBにも入れておけば後々便利だし(esだけでも良いけどね)。