More Related Content Similar to NGINX App Protect on Hatobaで実現するセキュリティサービス公開 構築手順書 (20) More from 富士通クラウドテクノロジーズ株式会社 (20) NGINX App Protect on Hatobaで実現するセキュリティサービス公開 構築手順書1. NGINX App Protect on Hatoba
で実現するセキュアなサービス公開
構築⼿順書
NGINX INGRESS CONTROLLERとWAFによる本番環境での安全なアプリケーションの実現
F5ネットワークスジャパン合同会社
ソリューションエンジニアリング部
シニアソリューションエンジニア
⼩峰 洋⼀
2. | ©2020 F5
2
注意事項
• 本⼿順書は、ニフクラのKubernetes Service Hatoba(以下Hatoba)上に
て、簡易的にNGINX Ingress Controller(以下NIC)とApp Protect(以
下NAP)の機能を持つIngress Controllerを構築、動作させるための⼿順書
となります。
• 検証以外でご利⽤頂く際には、ネットワークやセキュリティの設定等考慮
して構築してください。
• ニフクラやHatobaの各種設定の詳細はヘルプページをご確認ください。
4. | ©2020 F5
4
構築⼿順
(1) k8sクラスタの作成
(2) DVWAのデプロイ
(3) NGINX評価ライセンスの取得
(4) NIC/NAPのビルド
(5) NIC/NAPのデプロイ
(6) Ingressの設定と疎通確認
(7) ELKの構築
(8) NAPの設定
(9) NIC/NAPとELKの接続
(10) チューニングの実施
9. | ©2020 F5
9
(4)NIC/NAPのビルド
NGINXのサイトから必要なファイルをダウンロードし、ビルドしてコンテナイメージを作成後、⾃
分のDocker Hubプライベートリポジトリにアップします。
① 下記のビルド環境を準備してください。
参考ページ
https://docs.nginx.com/nginx-ingress-controller/app-protect/installation/
https://docs.nginx.com/nginx-ingress-controller/installation/building-ingress-controller-image/
https://www.nginx.co.jp/products/products-nginx/kubernetes-ingress-controller/
② Docker Hubの準備をしてください。
・無料アカウントの登録
・Private Repositoryの作成
名前は nginx-plus-ingress としてください。
後ほど指定します。
10. | ©2020 F5
10
(4)NIC/NAPのビルド
③ 必要なファイルをダウンロードしてビルドしてください。
● ダウンロード
$ git clone https://github.com/nginxinc/kubernetes-ingress/
任意の場所へダウンロードしてください。
● 評価ライセンスファイルの移動
ダウンロードした評価ライセンスファイル(nginx-repo.crt、nginx-repo.key)を、
<NGINX DIR>/kubernetes-ingress ディレクトリに移動してください。
● カレントディレクトリの移動
<NGINX DIR>/kubernetes-ingress ディレクトリに移動してください。
● dockerログイン
$ docker login
Docker Hubアカウントへログインしてください。
保存したディレクトリを<NGINX DIR>と
します。後ほどこの<NGINX DIR>に移動して頂く
事があります。
例︓
/root 直下で git clone を⾏った場合は、
<NGINX DIR> = /root
となります。
11. | ©2020 F5
11
(4)NIC/NAPのビルド
● NGINXバージョンを確認してcheck out
$ git tag
バージョンが表⽰されるので、最新版を確認してください。(例: v1.12.0)
$ git checkout v1.12.0 ← 最新版を指定
●ビルドの実⾏
$ make debian-image-nap-plus VERSION=<version> PREFIX=<docker hub ID>/nginx-plus-
ingress TARGET=container
<version>には最新版を指定し、<docker hub ID>には⾃分のIDを指定してください。
● Docker Hub プライベートリポジトリにアップ
$ make push PREFIX=<docker hub ID>/nginx-plus-ingress VERSION=<version>
● 確認
Docker Hubにアップされているか確認してください。
※ 本⼿順書執筆時点では最新バージョンがv1.12.0となっています。NGINX
v1.12.0はk8s v1.21までの対応となっており、k8s v1.22ではデプロイでき
ません。k8s v1.22以降をご利⽤の場合はNGIXNの対応バージョンがリリー
スされるのをお待ち下さい。
12. | ©2020 F5
12
(5)NIC/NAPのデプロイ
Docker Hubプライベートリポジトリにアップしたイメージをデプロイします。
① マニフェストファイルの確認
<NGINX DIR>/kubernetes-ingress/deployments に含まれているマニフェストファイルを適⽤し
ます。 <NGINX DIR>/kubernetes-ingress/deployments ディレクトリに移動してください。
$ pwd
<NGINX DIR>/kubernetes-ingress/deployments
$ ls
README.md common daemon-set deploymenthelm-chart rbac service
13. | ©2020 F5
13
(5)NIC/NAPのデプロイ
② マニフェストファイルの適⽤
下記順番で適⽤してください。
$ kubectl apply -f common/ns-and-sa.yaml
$ kubectl apply -f rbac/rbac.yaml
$ kubectl apply -f rbac/ap-rbac.yaml
$ kubectl apply -f common/default-server-secret.yaml
$ kubectl apply -f common/nginx-config.yaml
$ kubectl apply -f common/ingress-class.yaml
$ kubectl apply -f common/crds/k8s.nginx.org_virtualservers.yaml
$ kubectl apply -f common/crds/k8s.nginx.org_virtualserverroutes.yaml
$ kubectl apply -f common/crds/k8s.nginx.org_transportservers.yaml
$ kubectl apply -f common/crds/k8s.nginx.org_policies.yaml
$ kubectl apply -f common/crds/k8s.nginx.org_globalconfigurations.yaml
$ kubectl apply -f common/crds/appprotect.f5.com_aplogconfs.yaml
$ kubectl apply -f common/crds/appprotect.f5.com_appolicies.yaml
$ kubectl apply -f common/crds/appprotect.f5.com_apusersigs.yaml
参考ページ
https://docs.nginx.com/nginx-ingress-controller/installation/installation-
with-manifests/#configure-rbac
14. | ©2020 F5
14
(5)NIC/NAPのデプロイ
③ イメージのデプロイ
● プライベートリポジトリアクセス⽤のSecretの作成
$ kubectl create secret docker-registry private-reg-cred --docker-username=<docker hub
ID> --docker-password=<docker hub password> --docker-email=<email address> --
namespace=nginx-ingress
● マニフェストファイルの修正と適⽤
<NGINX DIR>/kubernetes-ingress/deployments/deployment/nginx-plus-ingress.yaml
修正後適⽤してください。
⾃分のプライベートリポジトリを指定してください。
- image: <docker hub ID>/nginx-plus-ingress:1.20.0
ここに先程作成した下記を追加してください。
serviceAccountName: nginx-ingress
imagePullSecrets:
- name: private-reg-cred
containers:
15. | ©2020 F5
15
(6)Ingressの設定と疎通確認
起動したNICとNAPの設定を⾏い、外部に公開して疎通確認を⾏います。
● マニフェストファイルの修正と適⽤
<NGINX DIR>/kubernetes-ingress/deployments/service/loadbalancer.yaml
修正後適⽤してください。
Nameからハイフンを削除してください。
nginx-ingress → nginxingress
※ 命名規則について
kind: Service、type: LoadBalancer のマニフェストにて、nameのみを指定してそこにハイフ
ンを使⽤することができません(7⽉時点での制限)。
もしハイフン等をご利⽤になられたい場合、アノテーションを利⽤してロードバランサーの名前
を別途指定することでハイフン等を使⽤できるようになります。詳しくは下記をご確認ください。
https://pfs.nifcloud.com/spec/kubernetes-service-hatoba/load_balancer.htm
本件について、ご不明点があれば下記ニフクラのお問い合わせページよりお問い合わせください。
https://pfs.nifcloud.com/inquiry/support.htm
16. | ©2020 F5
16
(6)Ingressの設定と疎通確認
● 疎通確認
IPアドレスを確認し、ブラウザからアクセスしてください。NGINXの404ページが表⽰されば疎通は問題
ありません。
(まだVirtualServer(Ingress)の設定を⾏っていないため現段階では404となります。)
$ kubectl get service -n nginx-ingress
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginxingress LoadBalancer xx.xx.xx.xx yy.yy.yy.yy 80:32583/TCP,443:31942/TCP 4m
ブラウザから http://yy.yy.yy.yy/ にアクセスし
404ページを確認してください。
17. | ©2020 F5
17
(6)Ingressの設定と疎通確認
● DVWAアプリケーションを接続
NGINXのCRDである VirtualServer でDVWAと接続します。
右記マニフェストファイルでDVWA Serviceを作成してください。
参考ページ︓ VirtualServerとは・・
https://docs.nginx.com/nginx-ingress-
controller/configuration/virtualserver-and-virtualserverroute-resources/
apiVersion: v1
kind: Service
metadata:
name: dvwa-svc
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
selector:
app: dvwa
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: nginx-vs
spec:
host: <external IP>
upstreams:
- name: dvwa
service: dvwa-svc
port: 80
routes:
- path: /dvwa
action:
proxy:
upstream: dvwa
rewritePath: /
左記マニフェストファイルでNGINXのVirtualServerを作成してください。
<external IP>には前ページの yy.yy.yy.yy を設定してください。
ブラウザから http://yy.yy.yy.yy/dvwa/
にアクセスし、ログインページが表⽰される
ことを確認してください。
service-dvwa.yaml
virtualserver-nginx.yaml
18. | ©2020 F5
18
(6)Ingressの設定と疎通確認
● DVWAアプリケーションのセットアップ
最初は何も⼊⼒せずに Login
ボタンをクリックしてください。
Create / Reset Database ボタンを
クリックしてください。404ページが
表⽰されますが問題ありません。
初期設定がされていますので、念の為
30秒ほどそのままお待ち下さい。
再度 http://yy.yy.yy.yy/dvwa/ にア
クセスし、下記情報でログインしてく
ださい。
Username: admin
Password: password
19. | ©2020 F5
19
(7)ELKの構築 ELKを起動する仮想サーバを構築し、その上にELKを構築します。
① 仮想サーバを構築してください。
SSHキーを作成して保存しておいてください。
下記3つをINルールに設定してください。
(1) SSH(TCP port 22)でのアクセス
(2) KibanaへのHTTP(TCP port 5601)でのアクセス
(3) NIC/NAPからデータを送信(TCP port 5144)
(1)(2)については適切なアドレスを設定してください。
(3)については、Hatoba k8s内のPodからのアクセスとな
りますが、送信元アドレスがk8sノードのIPアドレスで
NATされるため、ノードのIPアドレスを指定することにな
ります。実際の環境ではノード数の増減も考えられるため、
適切な運⽤をご検討ください。
CentOSを選択してください。
ここでは1vCPU/1GBを選択していますが、
⼤きい分には問題ありません。
20. | ©2020 F5
20
(7)ELKの構築
② ELKを構築してください。
● SSHで接続
$ chmod 700 elkserverkey_private.pem
$ ssh root@<global IP> -i elkserverkey_private.pem
仮想サーバ作成時にダウンロードしたSSHキーを指定してください。
● モジュールインストール
下記コマンドにて、必要なモジュールをインストールしてください。
Update: [root@localhost ~]# yum update
Git: [root@localhost ~]# yum install git
Docker: [root@localhost ~]# yum install docker
jq: [root@localhost ~]# yum install jq
※ dockerインストールにてpodmanがインストールされることにより、後の⼿
順のdocker runコマンド実⾏時、ボリュームマウント関連でエラーとなる
ケースがあるようです。その場合は「Centos8 docker インストール」等で
検索して頂き、別の⼿順(wgetでdocker関連インストーラをダウンロード
等)をお試しください。
21. | ©2020 F5
21
(7)ELKの構築
● テンプレートダウンロード
[root@localhost ~]# git clone https://github.com/f5devcentral/f5-waf-elk-dashboards.git
場所は任意ですが、今回は root 直下にクローンしてください。
● チューニング
[root@localhost ~]# vi /etc/sysctl.d/99-sysctl.conf
vm.max_map_count = 262144 ← ファイルの⼀番下に左記を追加して保存してください。
● 再起動
[root@localhost ~]# reboot
諸々設定を⾏ったので、再起動をしてください。
再起動後、設定が反映されていることを確認してください。
確認︓ [root@localhost ~]# sysctl -p
vm.max_map_count = 262144
22. | ©2020 F5
22
(7)ELKの構築
● SELinuxの設定
ディレクトリマウントに失敗しないように、SELinuxを無効にしておきます。(本環境以外では適切に設定
してください)
# setenforce 0
● docker run でELKを起動
[root@localhost ~]# docker run -d -v /root/f5-waf-elk-
dashboards/logstash/conf.d:/etc/logstash/conf.d -p 5601:5601 -p 9200:9200 -p 5144:5144 -it -
e ES_CONNECT_RETRY=300 --name elk sebp/elk
起動するまでお待ち下さい。数分かかります。
http://<global IP>:5601 にアクセスして
正常に画⾯が表⽰されれば⼤丈夫です。
docker run実⾏時にイメージ選択
が必要となった場合、docker.ioの
イメージを選択してください。
23. | ©2020 F5
23
(7)ELKの構築
● テンプレートのインポート
[root@localhost ~]# KIBANA_URL=http://<global IP>:5601
<global IP>に、仮想サーバのIPを指定してください。
[root@localhost ~]# jq -s . /root/f5-waf-elk-dashboards/kibana/overview-dashboard.ndjson | jq
'{"objects": . }' | curl -k --location --request POST
"$KIBANA_URL/api/kibana/dashboards/import" --header 'kbn-xsrf: true' --header 'Content-Type:
text/plain' -d @- | jq
[root@localhost ~]# jq -s . /root/f5-waf-elk-dashboards/kibana/false-positives-
dashboards.ndjson | jq '{"objects": . }' | curl -k --location --request POST
"$KIBANA_URL/api/kibana/dashboards/import" --header 'kbn-xsrf: true' --header 'Content-Type:
text/plain' -d @- | jq
参考ページ https://github.com/f5devcentral/f5-waf-elk-dashboards
26. | ©2020 F5
26
(8)NAPの設定
② NAPの設定
● App Protectの有効化
下記ファイルを修正してください。
<NGINX DIR>/kubernetes-ingress/deployments/deployment/nginx-plus-ingress.yaml
修正後適⽤してください。
コメントを外し、1⾏新たに追加してください。
参考ページ
https://docs.nginx.com/nginx-ingress-controller/app-protect/installation/
https://docs.nginx.com/nginx-ingress-controller/configuration/policy-resource/
27. | ©2020 F5
27
(8)NAPの設定
● Policyの作成
下記マニフェストファイルを適⽤してください。
参考ページ
https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-
manifests/#create-common-resources
https://docs.nginx.com/nginx-ingress-controller/app-
protect/configuration/#app-protect-policies/
apiVersion: appprotect.f5.com/v1beta1
kind: APPolicy
metadata:
name: default-policy
spec:
policy:
name: default-policy
template:
name: POLICY_TEMPLATE_NGINX_BASE
apiVersion: k8s.nginx.org/v1
kind: Policy
metadata:
name: waf-default-policy
spec:
waf:
enable: true
apPolicy: "default/default-policy"
$ kubectl get appolicy
NAME AGE
default-policy 4m9s
$ kubectl get policy
NAME STATE AGE
waf-default-policy Valid 55s
default-policy.yaml policy.yaml
28. | ©2020 F5
28
(8)NAPの設定
● VirtualServerにPolicyを設定
(6)で作成したVirtualServerリソースにポリシーの指定を追加し、適⽤してください。
参考ページ
https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-
manifests/#create-common-resources
https://docs.nginx.com/nginx-ingress-controller/app-
protect/configuration/#app-protect-policies/
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: nginx-vs
spec:
host: yy.yy.yy.yy
policies:
- name: waf-default-policy
upstreams:
- name: dvwa
service: dvwa-svc
port: 80
・・・
・・・
こちらを追加します。
その後、同じようにDVWAにアクセスして
SQL Injectionを実⾏してください。
NAPによって攻撃がブロックされました。
virtualserver-nginx.yaml
29. | ©2020 F5
29
(9)NIC/NAPとELKの接続
NIC/NAPのログ設定を⾏い、ELKへログを送信します。
下記マニフェストファイルを適⽤してください。
apiVersion: appprotect.f5.com/v1beta1
kind: APLogConf
metadata:
name: logconf
spec:
filter:
request_type: all
content:
format: default
max_request_size: any
max_message_size: 5k
aplogconf.yaml
参考ページ
https://docs.nginx.com/nginx-ingress-controller/app-
protect/configuration/#app-protect-logs
$ kubectl get aplogconf
NAME AGE
logconf 5s
(8)で作成した policy.yaml を下記のように修正して適⽤してください。
apiVersion: k8s.nginx.org/v1
kind: Policy
metadata:
name: waf-default-policy
spec:
waf:
enable: true
apPolicy: "default/default-policy”
securityLog:
enable: true
apLogConf: "default/logconf"
logDest: "syslog:server=<global IP>:5144"
policy.yaml
こちらを追加します。
<global IP>には、Kibanaにアクセスする際の
アドレスと同じものを指定してください。
31. | ©2020 F5
31
(10)チューニングの実施
デフォルトで設定しているセキュリティポリシーを修正し、チューニングを⾏ってみます。
● デフォルトのポリシー
(8)で指定した右記のポリシーがデフォルトのポリシーとなります。
POLICY_TEMPLATE_NGINX_BASEというテンプレートを使⽤し、
OWASP TOP10への対応等、基本的な攻撃に対してのテンプレート
となります。
具体的なテンプレートの中⾝は参考ページと
NIC Pod内にある下記ファイルに記載されています。
/opt/app_protect/install/policy_templates/nginx_base.xml
apiVersion: appprotect.f5.com/v1beta1
kind: APPolicy
metadata:
name: default-policy
spec:
policy:
name: default-policy
template:
name: POLICY_TEMPLATE_NGINX_BASE
default-policy.yaml
参考ページ
https://docs.nginx.com/nginx-app-
protect/configuration/#signature-sets-in-default-policy
33. | ©2020 F5
33
(10)チューニングの実施
● Botへの対応
現在の設定で curl でアクセスしてください。
# curl http://yy.yy.yy.yy/dvwa/login.php
正しくHTMLが返され、Kibanaには下記のように表⽰
されると思います。
デフォルトのテンプレートだと alerted となっていま
すがcurlを含むBotからのアクセスをブロックする
チューニングを⾏ってみます。
curlアクセスする度にCountが増加します。
34. | ©2020 F5
34
(10)チューニングの実施
デフォルトのポリシーでは、Bot Defenseがtrueになっています。curlは untrust Botに分類されます。
apiVersion: appprotect.f5.com/v1beta1
kind: APPolicy
metadata:
name: default-policy
spec:
policy:
name: default-policy
template:
name: POLICY_TEMPLATE_NGINX_BASE
現⾏default-policy.yaml
/opt/app_protect/install/policy_templates/nginx_base.xml
※NIC Pod内で確認
<?xml version="1.0" encoding="utf-8"?>
<policy bigip_version="15.1.0"
name="/Common/NGINX_BASE_TEMPLATE">
<type>Security</type>
<encoding>utf-8</encoding>
<description>Base Template for NGINX
Standalone</description>
---(略)---
<bot_defense>
<settings>
<enabled>true</enabled>
</settings>
</bot_defense>
</policy>
Base Templateではデフォルトで
Bot Defenseがtrueになっています。
Bot type Action
trusted detect
untrust alarm
malicious block
デフォルトのアクション
35. | ©2020 F5
35
(10)チューニングの実施
● チューニング
Untrust BotをBlockする設定を追加し、適⽤してください。
apiVersion: appprotect.f5.com/v1beta1
kind: APPolicy
metadata:
name: default-policy
spec:
policy:
name: default-policy
template:
name: POLICY_TEMPLATE_NGINX_BASE
bot-defense:
mitigations:
classes:
- name: untrusted-bot
action: block
こちらを追加します。
default-policy.yaml
適⽤後再度curlでアクセスし、ブロックされることを確認します。
# curl http://yy.yy.yy.yy/dvwa/login.php
<html><head><title>Request Rejected</title></head><body>The requested URL
was rejected. Please consult with your administrator.<br><br>Your support ID is:
17145546028604397486<br><br><a href='javascript:history.back();'>[Go
Back]</a></body></html>
Kibana上でもブロックとしてカウントされています。
blockをalermにするか、追加部分を
削除することでもとにもどります。