こちらはAWS Containers Advent Calendar 2020の5日目の記事です。
ハニーポットとは、あえて外部から攻撃を受けることで最近の攻撃のトレンドや手法を見てみよう!という目的で構築されるサーバのことです。このハニーポット、運用をするにはハニポサーバそのものの整備だけではなくサーバで受けたログを収集し解析を行う解析基盤の整備です。
今回はハニーポットをAWS/EKS上に構築することで運用コストを抑えてみようというお話しです。
しかしせっかくのre:Inventの直後アドベントカレンダーですので、最近話題になっているAWS Fargateと先日のre:Inventで話題に上がったFargate上のログをfluentbitで収集する機構を用いてログの集約を行う環境を整えていこうと思います。
構成
今回のハニポは下記のような構成で構築しました。(fluentdではなくfluentbitの間違いですorz)
OSレイヤ以下のメンテナンスは極力したくないため & 新しいもの触りたいということで今回はAWS Fargateを利用します。
基本的に攻撃者にはALB経由で攻撃を行ってもらい、IngressでHTTPのポートを割り振ってPodでアクセスログをキャプチャしていく構成です。またログDBのバックエンドとしてElasticsearchかCloudWatchLogsで悩みましたが、お仕事で今後使う予定のCloudWatchLogsを利用することにしました。
ハニポとしてはWOWHoneypotを利用します。ただしオリジナルにはDockerコンテナ周りの設定が含まれていないため、今回はForkしたオレオレWOWHoneypotを利用することにします。
構築
環境構築
こちらに従って構築していきます。
https://aws.amazon.com/jp/blogs/containers/fluent-bit-for-amazon-eks-on-aws-fargate-is-here/
適当な踏み台サーバ上に、みなさん大好きawscli/elsctlをインストールしておきます。実際にはVPCの設定は細かく設定する必要がありますが、いったんサクッとeksctl側の設定に任せることにします。
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: honeypot
region: eu-west-2
version: "1.18"
cloudWatch:
clusterLogging:
enableTypes: ["*"]
iam:
withOIDC: true
fargateProfiles:
- name: kube-system
selectors:
- namespace: kube-system
- name: wowhoneypot
selectors:
- namespace: wowhoneypot
$ eksctl create cluster -f ./cluster.yaml
20分程度すると環境ができあがっています。環境が立ち上がったら.kubeconfig
に認証情報を保存してkubectl get pods --all-namewspaces
を叩いてCoreDNSのPodが立ち上がっていることを確認します。
$ aws eks update-kubeconfig --name honeypot
$ kubectl get pods --all-namespaces
$ kubectl create ns wowhoneypot
上記の構築でFargateProfileを一緒に作成されています。FargateProfileはKubernetesのNamespaceリソースとラベルを用いて指定することが可能ですが、今回はNamespaceリソースにだけ割り当てます。これによりwowhoneypot
namespaceに作成されたPodはすべてFargate上に起動するようになります。
ログ収集用IAM Policyの作成
アプリログをfluentbitが拾ってCloudWatch Logsへ投げ込む際に、FargateからCloudWatch Logsのリソースへアクセスする必要があります。そこでCloudWatch Logsへのアクセスを行うためのIAM Policyを作成し、Fargateの実行ロールへアタッチします。
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:CreateLogGroup",
"logs:DescribeLogStreams",
"logs:PutLogEvents"
],
"Resource": "*"
}]
}
# 先のCloudWatch LogsへアクセスするためのPolocyを作成する
$ aws iam create-policy \
--policy-name FluentBitEKSFargate \
--policy-document file://permissions.json
# FargateProfileのExecutionRoleを取得する
# RoleNameではなくARNが渡されるので注意
$ aws eks describe-fargate-profile \
--cluster-name honeypot \
--fargate-profile-name wowhoneypot \
--query fargateProfile.podExecutionRoleArn
# 作成したPolicyをRoleにアタッチする
$ aws iam attach-role-policy \
--policy-arn arn:aws:iam::123456789012:policy/FluentBitEKSFargate \
--role-name eksctl-honeypot-cluster-FargatePodExecutionRole-XXXXXXXXXX
EKS自体の環境構築はここでいったん完了です。
WOWHoneypotの改修
ハニーポット本体となるWOWHoneypotの改修ポイントとして下記の4点が必要です。
- ログのフォーマット
- jsonなどの構造化データに変更する
- 環境変数による設定の注入
- WOWHoneypotは独自のconfigフォーマットを用いている
- Client ipaddressの変更
- masterブランチではリクエストヘッダーの
Host
のIPアドレスをClientIPとしている
- masterブランチではリクエストヘッダーの
- Dockerfileの作成
特に今回はHTTPのエンドポイントとしてALBを利用するため、ClientIPの表示をヘッダーのX-Forwarded-For
の値に変更する必要があります。
ということでざっくり再実装したものがこちらのリポジトリ > https://github.com/RyuSA/WOWHoneypot
マニフェストの作成
aws-observability
namespaceを作成して、namespaceへ適切なラベルを貼るとfluentbitによるログ転送が有効になります。
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/fargate-logging.html
kind: Namespace
apiVersion: v1
metadata:
name: aws-observability
labels:
aws-observability: enabled
---
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-logging
namespace: aws-observability
labels:
k8s-app: fluentbit-cloudwatch
data:
output.conf: |
[OUTPUT]
Name cloudwatch_logs
Match *
region us-east-2
log_key log
log_group_name /app/honeypot
log_stream_name wowhoneypot
auto_create_group On
そしてDeploymentとServiceを作成します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: wowhoneypot
namespace: wowhoneypot
labels:
app: wowhoneypot
type: honeypot
spec:
replicas: 1
selector:
matchLabels:
app: wowhoneypot
template:
metadata:
labels:
app: wowhoneypot
spec:
containers:
- name: wowhoneypot
image: ryusa/wowhoneypot:1.4
imagePullPolicy: Always
resources:
requests: {}
limits:
cpu: 100m
memory: 64Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
env:
- name: "PORT"
value: "8080"
ports:
- containerPort: 8080
ここまで確認できたら動作確認をしておきましょう。
$ kubectl -n wowhoneypot port-forward wowhoneypot-XXX-YYY 8080:8080
$ curl localhost:8080/debug
$ kubectl -n wowhoneypot logs wowhoneypot-XXX-YYY
ALBのプロビショニング
Fargate上のPodへNodePortを指定することはできず、LoadBalancerとしてはALBを利用するほかありません。そこでIngressとしてALB Controllerをデプロイしエンドポイントとします。
まずはEKSがALBを構築するためのIAM Policyを作成します。
$ curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.9/docs/examples/iam-policy.json
$ aws iam create-policy --policy-name ALBIngressControllerIAMPolicy --policy-document file://iam-policy.json
IAM Policy作成後、今後はIAM Policyに紐つけるためのServiceAccountを作成しPolicyと紐付けを行います。
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.9/docs/examples/rbac-role.yaml
$ eksctl create iamserviceaccount \
--region us-east-2 \
--name alb-ingress-controller \
--namespace kube-system \
--cluster honeypot \
--attach-policy-arn arn:aws:iam::123456789012:policy/ALBIngressControllerIAMPolicy \
--override-existing-serviceaccounts \
--approve
あとはALBのプロビショニングを担当するALB Controllerをデプロイするだけです。ただしALB ControllerのマニフェストにはAWS環境について記載する箇所があるため注意が必要です。
$ curl -o alb-ingress-controller.yaml https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.9/docs/examples/alb-ingress-controller.yaml
# 下記をそれぞれコメント解除して記載する
# --cluster-name
# --aws-vpc-id
# --aws-region
$ vim alb-ingress-controller.yaml
$ kubectl create -f alb-ingress-controller.yaml -n kube-system
ALB ControllerがRunning Stateになった状態で、ALBをプロビショニングしましょう!
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: "endpoint"
namespace: "wowhoneypot"
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 8080}, {"HTTP": 80}]'
spec:
rules:
- http:
paths:
- path: /*
backend:
serviceName: wowhoneypot
servicePort: 8080
Ingressの作成が完了するまでやや時間がかかるので、AWSコンソールで構築状況を確認するかdigコマンドでIPが降ってくることを確認しておくと良いと思います。
LoadBalancerの作成が完了するとCloudWatchLogsにアクセスがポコポコ来るようになります。
完走した感想
1週間ほどハニポを放置してみましたが、定常的に5req/min程度の攻撃を観測することができ、某VPSのレンタルサーバでハニポを運用していた時よりアクセス数が多いかな?といった印象でした。(AWSのIPレンジとかで集中していたりするのかな?)
TCPレイヤの攻撃も見たかったのですが、EKS FargateはL4レイヤのLBに対応しておらず今回は断念しました。しかし同じ手法を使えばマネージドノードグループを利用することでTCPレイヤの攻撃も観測することができると思います。