Архитектура микросервисов — самая серьёзная угроза безопасности в кластере Kubernetes (K8s), так как каждое развёртываемое приложение открывает для злоумышленников новый потенциальный вектор атаки. При этом, развёрнутые приложения генерируют логи, а наша платформа CrowdSec может запускаться в контейнере. Значит, мы можем использовать её в кластере K8s для того, чтобы мониторить выбранные приложения и обнаруживать атаки на них.
Подготовка к работе
Перед тем, как мы приступим к практической части, убедитесь, что у вас есть:
настроенная учётная запись Amazon Web Services (AWS) и инструмент командной троки eksctl или готовый кластер K8s (убедитесь, что у кластера достаточно доступных ресурсов, хотя бы один процессор и 1 ГБ ОЗУ);
инструмент командной строки kubectl;
Менеджер пакетов helm.
Настройка тестового окружения
Развёртывание кластера K8s
Если у вас нет готового кластера, вы сможете достаточно быстро развернуть его при помощи сервиса Amazon EKS. Вот простая конфигурация для 1 инстанса t2.small:
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: alpaga
region: eu-west-1
version: "1.21"
nodeGroups:
- name: ng-1
instanceType: t2.small
desiredCapacity: 1
ssh:
allow: true
Если вам нужно создать больше узлов, просто измените параметр desiredCapacity.
Затем мы можем запустить эту конфигурацию для создания кластера:
$ eksctl create cluster -f cluster.yaml
2021-09-17 17:39:41 [] eksctl version 0.62.0
2021-09-17 17:39:41 [] using region eu-west-1
2021-09-17 17:39:41 [] setting availability zones to [eu-west-1a eu-west-1c eu-west-1b]
2021-09-17 17:39:41 [] subnets for eu-west-1a - public:192.168.0.0/19 private:192.168.96.0/19
2021-09-17 17:39:41 [] subnets for eu-west-1c - public:192.168.32.0/19 private:192.168.128.0/19
2021-09-17 17:39:41 [] subnets for eu-west-1b - public:192.168.64.0/19 private:192.168.160.0/19
2021-09-17 17:39:41 [] nodegroup "ng-1" will use "ami-044dfe22e0788d8ed" [AmazonLinux2/1.21]
2021-09-17 17:39:41 [] using SSH public key "/home/.ssh/id_rsa.pub" as "eksctl-alpaga-nodegroup-ng-1-7f:94:de:2d:82:df:52:b1:e1:56:4b:a6:7f:2e:91:72"
2021-09-17 17:39:42 [] using Kubernetes version 1.21
2021-09-17 17:39:42 [] creating EKS cluster "alpaga" in "eu-west-1" region with un-managed nodes
2021-09-17 17:39:42 [] 1 nodegroup (ng-1) was included (based on the include/exclude rules)
2021-09-17 17:39:42 [] will create a CloudFormation stack for cluster itself and 1 nodegroup stack(s)
...
2021-09-17 18:00:57 [] nodegroup "ng-1" has 0 node(s)
2021-09-17 18:00:57 [] waiting for at least 1 node(s) to become ready in "ng-1"
2021-09-17 18:01:49 [] nodegroup "ng-1" has 1 node(s)
2021-09-17 18:01:49 [] node "ip-192-168-68-125.eu-west-1.compute.internal" is ready
2021-09-17 18:03:51 [] kubectl command should work with "/home/.kube/config", try 'kubectl get nodes'
2021-09-17 18:03:51 [] EKS cluster "alpaga" in "eu-west-1" region is ready
При развёртывании кластера мы уже можем получить определённые данные:
$ kubectl cluster-info
Kubernetes control plane is running at https://XXXXXXXXXXXXXXXXXXXXXXXXXXXX.gr7.eu-west-1.eks.amazonaws.com
CoreDNS is running at https://XXXXXXXXXXXXXXXXXXXXXXXXXXXX.gr7.eu-west-1.eks.amazonaws.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Развертывание контроллера Nginx Ingress Controller
Чтобы установить контроллер, мы используем указанную в документации команду:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.0/deploy/static/provider/aws/deploy.yaml
После установки мы можем увидеть поды контроллера в новом пространстве имён:
$ kubectl -n ingress-nginx get pods
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-psc5c 0/1 Completed 0 78s
ingress-nginx-admission-patch-9qgrr 0/1 Completed 1 77s
ingress-nginx-controller-fd7bb8d66-llxc9 1/1 Running 0 79s
Установка приложения HelloWorld
В качестве тестового приложения мы предлагаем HelloWorld, которое можно развернуть с помощью контроллера Nginx. Этот пакет можно найти в нашем репозитории. Сперва нам необходимо установить репозиторий helm, затем приложение HelloWorld, а затем CrowdSec:
$ helm repo add crowdsec https://crowdsecurity.github.io/helm-charts
"crowdsec" has been added to your repositories
Затем мы обновим репозитории, чтобы получить новые пакеты.
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "crowdsec" chart repository
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈Happy Helming!⎈
Теперь мы можем установить пакет HelloWorld в пространство имён, выбранное по умолчанию и с параметрами по умолчанию.
$ helm install helloworld crowdsec/helloworld
W0920 12:22:22.434028 298463 warnings.go:70] networking.k8s.io/v1beta1 Ingress is deprecated in v1.19+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
W0920 12:22:22.792661 298463 warnings.go:70] networking.k8s.io/v1beta1 Ingress is deprecated in v1.19+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
NAME: helloworld
LAST DEPLOYED: Mon Sep 20 12:22:21 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
http://helloworld.local/
Чтобы получить доступ к этому URL-адресу, вам необходимо получить общедоступный IP-адрес и изменить файл вашего хоста:
$ kubectl get ingresses.networking.k8s.io
NAME CLASS HOSTS ADDRESS PORTS AGE
helloworld <none> helloworld.local a8523ec3bb4024bc3a7f8b26294013f3-c7ea4e370eaf1195.elb.eu-west-1.amazonaws.com 80 2m18s
$ host a8523ec3bb4024bc3a7f8b26294013f3-c7ea4e370eaf1195.elb.eu-west-1.amazonaws.com
a8523ec3bb4024bc3a7f8b26294013f3-c7ea4e370eaf1195.elb.eu-west-1.amazonaws.com has address 52.31.225.95
a8523ec3bb4024bc3a7f8b26294013f3-c7ea4e370eaf1195.elb.eu-west-1.amazonaws.com has address 54.73.240.30
a8523ec3bb4024bc3a7f8b26294013f3-c7ea4e370eaf1195.elb.eu-west-1.amazonaws.com has address 176.34.92.134
При использовании EKS AWS выполнение этой команды может занять некоторое время. Мы можем изменить файл хоста, чтобы добавить один из общедоступных IP-адресов:
echo "52.31.225.95 helloworld.local" | sudo tee -a /etc/hosts
Теперь мы получили доступ к нашему приложению:
$ curl -v http://helloworld.local
* Trying 52.31.225.95:80...
* TCP_NODELAY set
* Connected to helloworld.local (52.31.225.95) port 80 (#0)
> GET / HTTP/1.1
> Host: helloworld.local
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Mon, 20 Sep 2021 10:38:21 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 13
< Connection: keep-alive
< X-App-Name: http-echo
< X-App-Version: 0.2.3
<
helloworld!
* Connection #0 to host helloworld.local left intact
Мы также можем просмотреть логи Nginx, чтобы увидеть лог HTTP:
$ k -n ingress-nginx logs ingress-nginx-controller-fd7bb8d66-llxc9
82.125.X.X - - [20/Sep/2021:10:38:21 +0000] "GET / HTTP/1.1" 200 13 "-" "curl/7.68.0" 80 0.001 [default-helloworld-5678] [] 192.168.65.115:5678 13 0.000 200 abb8f358776224ff5c14a6c0a227b450
Наша среда готова!
Установка CrowdSec
Пакет CrowdSec также доступен в нашем репозитории пакетов.
Сперва необходимо создать новое пространство имён:
$ kubectl create ns crowdsec
namespace/crowdsec created
Мы планируем мониторить логи Nginx, потому что наше тестовое приложение связано с этим контроллером. Для настройки пакета CrowdSec мы создадим новый файл crowdsec-values.yaml:
agent:
# To specify each pod you want to process it logs (pods present in the node)
acquisition:
# The namespace where the pod is located
- namespace: ingress-nginx
# The pod name
podName: ingress-nginx-controller-*
# as in crowdsec configuration, we need to specify the program name so the parser will match and parse logs
program: Nginx
# Those are ENV variables
env:
# As it's a test, we don't want to share signals with CrowdSec so disable the Online API.
- name: DISABLE_ONLINE_API
value: "true"
# As we are running Nginx, we want to install the Nginx collection
- name: COLLECTIONS
value: "crowdsecurity/nginx"
lapi:
env:
# As it's a test, we don't want to share signals with CrowdSec, so disable the Online API.
- name: DISABLE_ONLINE_API
value: "true"
Если вы хотите изменить переменные среды образа Docker, вы можете ознакомиться с данным руководством.
Теперь мы можем установить CrowdSec, используя файл конфигурации в пространстве имён CrowdSec, которое мы создали ранее:
$ helm install crowdsec crowdsec/crowdsec -f crowdsec-values.yaml -n crowdsec
NAME: crowdsec
LAST DEPLOYED: Mon Sep 20 17:46:02 2021
NAMESPACE: crowdsec
STATUS: deployed
REVISION: 1
TEST SUITE: None
Теперь наш агент и LAPI (локальное API CrowdSec) запущены:
$ k get pods -n crowdsec
NAME READY STATUS RESTARTS AGE
crowdsec-agent-kf9fr 1/1 Running 0 34s
crowdsec-lapi-777c469947-jbk9q 1/1 Running 0 34s
Чтобы проверить, способен ли CrowdSec обнаруживать атаки, мы смоделируем атаку на приложение HelloWorld с помощью сканера уязвимостей. Мы запустим атаку с помощью этой команды после установки Nikto (запустите атаку и отмените ее через 20 секунд, просто чтобы сгенерировать логи о нескольких атаках на приложение):
$ ./nikto.pl -host http://helloworld.local
Теперь мы можем запустить shell в модуле агента CrowdSec и увидеть метрики и предупреждения, которые сгенерируют эти атаки:
$ kubectl -n crowdsec exec -it crowdsec-agent-vn4bp -- sh
/ # cscli metrics
INFO[21-09-2021 09:39:50 AM] Buckets Metrics:
+-------------------------------------------+---------------+-----------+--------------+--------+---------+
| BUCKET | CURRENT COUNT | OVERFLOWS | INSTANCIATED | POURED | EXPIRED |
+-------------------------------------------+---------------+-----------+--------------+--------+---------+
| crowdsecurity/http-bad-user-agent | 3 | 183 | 186 | 369 | - |
| crowdsecurity/http-crawl-non_statics | - | 7 | 9 | 351 | 2 |
| crowdsecurity/http-path-traversal-probing | - | - | 1 | 2 | 1 |
| crowdsecurity/http-probing | 1 | - | 2 | 2 | 1 |
| crowdsecurity/http-sensitive-files | - | 3 | 4 | 17 | 1 |
+-------------------------------------------+---------------+-----------+--------------+--------+---------+
INFO[21-09-2021 09:39:50 AM] Acquisition Metrics:
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+--------------+----------------+------------------------+
| SOURCE | LINES READ | LINES PARSED | LINES UNPARSED | LINES POURED TO BUCKET |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+--------------+----------------+------------------------+
| file:/var/log/containers/ingress-nginx-controller-fd7bb8d66-llxc9_ingress-nginx_controller-c536915796f13bbf66d1a8ab7159dbd055773dbbf89ab4d9653043591dfaef1f.log | 371 | 371 | - | 741 |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+--------------+----------------+------------------------+
INFO[21-09-2021 09:39:50 AM] Parser Metrics:
+--------------------------------+------+--------+----------+
| PARSERS | HITS | PARSED | UNPARSED |
+--------------------------------+------+--------+----------+
| child-crowdsecurity/http-logs | 1113 | 738 | 375 |
| child-crowdsecurity/nginx-logs | 371 | 371 | - |
| crowdsecurity/dateparse-enrich | 371 | 371 | - |
| crowdsecurity/docker-logs | 371 | 371 | - |
| crowdsecurity/geoip-enrich | 371 | 371 | - |
| crowdsecurity/http-logs | 371 | 360 | 11 |
| crowdsecurity/nginx-logs | 371 | 371 | - |
| crowdsecurity/whitelists | 371 | 371 | - |
+--------------------------------+------+--------+----------+
Метрики показывают файлы, прочитанные CrowdSec (в таблице сбора данных), количество проанализированных/непроанализированных файлов, и все сценарии, которые были запущены в результате чтения логов. В установленной нами коллекции Crowdsecurity/Nginx уже содержалось несколько сценариев для обнаружения HTTP-атак.
Теперь посмотрим, обнаруживает ли агент CrowdSec атаки от Nikto:
/ # cscli alerts list
+----+------------------+--------------------------------------+---------+---------+-----------+--------------------------------+
| ID | VALUE | REASON | COUNTRY | AS | DECISIONS | CREATED AT |
+----+------------------+--------------------------------------+---------+---------+-----------+--------------------------------+
| 3 | Ip:82.125.X.X | crowdsecurity/http-sensitive-files | FR | Orange | ban:1 | 2021-09-21 09:38:12.624461519 |
| | | | | | | +0000 UTC |
| 2 | Ip:82.125.X.X | crowdsecurity/http-crawl-non_statics | FR | Orange | ban:1 | 2021-09-21 09:38:12.104034837 |
| | | | | | | +0000 UTC |
| 1 | Ip:82.125.X.X | crowdsecurity/http-bad-user-agent | FR | Orange | ban:1 | 2021-09-21 09:38:12.104018425 |
| | | | | | | +0000 UTC |
+----+------------------+--------------------------------------+---------+---------+-----------+--------------------------------+
Это предупреждения, созданные агентом CrowdSec после сканирования Nikto. Мы видим, что было запущено несколько сценариев, и агент отправил решения о бане в LAPI. Это означает, что в дальнейшем эти решения будут сохранены и переданы баунсерам, которые заблокируют этот IP.
"Прибираем" за собой
Чтобы устранить последствия наших тестов, достаточно выполнить пару простых действий:
— если вы развернули собственный кластер, его можно быстро удалить его при помощи eksctl:
eksctl delete cluster -f cluster.yaml
— если вы использовали существующий кластер, необходимо удалить пакеты, которые мы в него добавили:
$ helm delete crowdsec -n crowdsec
$ helm delete helloworld
Если вы установили Nginx, его также можно удалить при помощи команды:
kubectl delete -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.0/deploy/static/provider/aws/deploy.yaml
Заключение
В этом посте мы описали возможности установки CrowdSec в Kubernetes и то, как наша платформа может обнаруживать атаки. Но обнаружение не будет приносить пользы без предотвращения атак. В данный момент мы работаем над внедрением баунсеров в Kubernetes для блокировки обнаруженных атак. Мы начнём с интеграции Lua в Nginx и после завершения этого процесса опишем в новом посте, как использовать баунсеры, чтобы защитить свои приложения от атак.
Надеемся, вам понравился этот обзор. Будем рады услышать ваше мнение по поводу использования CrowdSec в Kubernetes.
Команда CrowdSec
ZhilyaevDmitriy
Спасибо за статью, не знал о существование данного инструмента.
Обещаете поддержку lua в nginx. А если у меня traefik / envoy / etc?
А можно ли будет выгружать какие-то репорты? Или как-то это дело отправить в тот же prometheus?
CrowdSec Автор
Спасибо вам. Рады, что CrowdSec вас заинтeресовал! Наш баунсер traefik можно найти здесь: https://github.com/fbonalair/traefik-crowdsec-bouncer. Envoy пока еще нет, но посмотрите наш хаб, там собраны другие баунсеры https://hub.crowdsec.net/browse/#bouncers
Для репортов есть Metabase, интеграция prometheus, а также наша Консоль https://app.crowdsec.net/