[자작NAS] 우분투 서버에 Docker로 CrowdSec 설치
CrowdSec은 침입 방지 시스템으로 외부의 침입 시도로부터 서버를 보호합니다.
Fail2ban과 유사한 역할을 하지만 동작 방식은 조금 다릅니다.
Fail2ban은 각 서비스의 로그들을 스캔해서 실패한 로그인 등에 대한 로그를 기반으로 IP를 차단합니다.
CrowdSec는 CrowdSec을 설치한 사람들의 로그를 분석해서 각 사용자로부터 수집한 악성 IP들을 차단합니다.
여러 사용자들이 공유하는 정보를 기반으로 IP를 차단하기 때문에 더 많은 정보를 활용할 수 있습니다.
또한, CrowdSec은 Traefik이나 Cloudflare 등과 같은 서비스와 연동하기 위한 바운서(Bouncers)를 제공합니다.
CrowdSec을 적용해서 서버의 보안을 강화시키는 방법을 알아보겠습니다.
1. CrowdSec 설정
CrowdSec 설치는 아래 링크를 참조해서 작성되었습니다.
먼저 다음 링크를 참조해서 Traefik을 설치합니다.
2023.07.20 - [IT/NAS] - [자작NAS] 우분투 서버에 Docker로 Traefik 설치
Traefik이 정상적으로 동작하면 CrowdSec과 Traefik을 위한 바운서를 실행할 수 있습니다.
Traefik이 이미 설정된 docker-compose.yml 파일에 다음 내용을 추가로 입력합니다.
whoami가 있던 부분을 삭제하고 입력하면 됩니다.
crowdsec:
image: crowdsecurity/crowdsec
container_name: crowdsec
env_file: .env
environment:
- COLLECTIONS=${CROWDSEC_COLLECTIONS}
- GID=${PGID}
depends_on:
traefik:
condition: service_healthy
volumes:
- ${CROWDSEC_PATH}/data:/var/lib/crowdsec/data
- ${CROWDSEC_PATH}/config:/etc/crowdsec
- ${TRAEFIK_PATH}/logs:/logs/traefik:ro
- /var/log:/var/log:ro
networks:
- web
restart: always
traefik-bouncer:
image: fbonalair/traefik-crowdsec-bouncer
container_name: traefik-bouncer
env_file: .env
environment:
- GIN_MODE=release
- CROWDSEC_BOUNCER_API_KEY=${CROWDSEC_KEY_TRAEFIK} # cscli bouncers add traefik-bouncer
- CROWDSEC_BOUNCER_LOG_LEVEL=2
- CROWDSEC_AGENT_HOST=crowdsec:8080
networks:
- web
restart: always
그리고 필요한 환경변수를 추가해 줍니다.
기존에 Traefik을 위해 추가한 내용에 아래 내용을 추가로 더해주면 됩니다.
# Common
PGID=1000
# CrowdSec
CROWDSEC_KEY_TRAEFIK=키입력
CROWDSEC_PATH=/data/crowdsec
CROWDSEC_COLLECTIONS=crowdsecurity/base-http-scenarios crowdsecurity/http-cve crowdsecurity/iptables crowdsecurity/linux crowdsecurity/nginx crowdsecurity/sshd crowdsecurity/traefik Dominic-Wagner/vaultwarden LePresidente/grafana
.env 파일의 키입력 부분은 crowdsec을 실행한 후에 생성할 수 있습니다.
이제 crowdsec을 먼저 실행합니다.
sudo docker compose up -d crowdsec
crowdsec이 실행되면 다음 명령어로 설정한 컬렉션들이 정상적으로 표시되는지 확인합니다.
sudo docker compose exec -t crowdsec cscli collections list
다음과 같은 형태로 활성화되어 있는 것을 볼 수 있습니다.
일단 CrowdSec이 실행이 완료되면 추가적인 설정들을 진행해야 합니다.
2. 로그 설정
다음으로 acquis.yaml 파일을 수정해서 Traefik 로그를 읽도록 해줍니다.
sudo nano /data/crowdsec/config/acquis.yaml
다음과 같이 내용을 입력합니다.
filenames:
- /var/log/nginx/*.log
- ./tests/nginx/nginx.log
#this is not a syslog log, indicate which kind of logs it is
labels:
type: nginx
---
filenames:
- /var/log/auth.log
- /var/log/syslog
- /var/log/kern.log
labels:
type: syslog
---
filename: /var/log/apache2/*.log
labels:
type: apache2
---
filenames:
- /logs/traefik/*.log
labels:
type: traefik
Nginx나 Apache 서버가 없다면 해당 부분(type: nginx, type: apache2)은 삭제해도 됩니다.
설정이 완료되면 CrowdSec을 재시작합니다.
sudo docker compose restart crowdsec
다음 명령어로 추가된 로그 파일들을 읽고 있는지 확인할 수 있습니다.
sudo docker compose exec -t crowdsec cscli metrics
시간이 지나고 로그 파일들을 파싱하고 나면 다음과 같이 결과가 나옵니다.
파일을 읽기 전까지 일부 파일이 표시되지 않을 수도 있습니다.
3. 화이트 리스트 작성
다음 명령어를 실행해서 접속을 허용할 목록을 추가해 줍니다.
sudo nano /data/crowdsec/config/parsers/s02-enrich/mywhitelists.yaml
다음과 같이 입력해 주면 됩니다.
name: crowdsecurity/whitelists
description: "Whitelist events from my ip addresses"
whitelist:
reason: "my ip ranges"
ip:
- "xxx.xxx.xxx.xxx"
- "127.0.0.1"
cidr:
- "192.168.0.0/16"
- "10.0.0.0/8"
- "172.16.0.0/12"
xxx.xxx.xxx.xxx 부분은 본인의 실제 외부 IP로 입력하면 됩니다.
IP가 자주 변동되는 유동 IP라면 생략해도 됩니다.
이제 컨테이너를 재시작해서 적용하면 됩니다.
sudo docker compose restart crowdsec
이것으로 화이트 리스트 설정이 완료됩니다.
4. MariaDB 연동하기 (생략 가능)
CrowdSec은 기본적으로 SQLite를 기본 DB로 사용합니다.
데이터가 많아지면 SQLite가 느릴 수 있기 때문에 별도의 DBMS에 연결해서 사용하는 것이 가능합니다.
기본 SQLite를 계속 사용하려는 경우 이 단계는 건너뛰어도 됩니다.
여기서는 MariaDB(MySQL)을 연동하는 방법을 알아보겠습니다.
MariaDB를 Docker Compose로 실행하는 방법은 아래 링크에서 확인 가능합니다.
2023.07.24 - [IT/NAS] - [자작NAS] 우분투 서버에 Docker로 MariaDB 설치
다음 명령어로 MariaDB 컨테이너 접속합니다.
sudo docker compose exec -it mariadb mariadb -u root -p
root 계정의 비밀번호를 입력하고 접속한 후 다음 명령어들을 순차적으로 입력합니다.
CREATE DATABASE crowdsec;
CREATE USER 'crowdsec'@'%' IDENTIFIED BY '비밀번호';
GRANT ALL PRIVILEGES ON crowdsec.* TO 'crowdsec'@'%';
FLUSH PRIVILEGES;
quit
비밀번호 부분은 원하는 비밀번호로 변경하면 됩니다.
그리고 CrowdSec의 config.yaml 파일을 수정해 주면 됩니다.
sudo nano /data/crowdsec/config/config.yaml
db_config 부분을 찾아서 다음과 같이 MariaDB를 사용하도록 변경해 주면 됩니다.
db_config:
log_level: info
type: mysql
user: crowdsec
password: 비밀번호
db_name: crowdsec
host: mariadb
port: 3306
flush:
max_items: 5000
max_age: 7d
다음으로 docker-compose.yml 파일의 CrowdSec 부분도 일부 변경합니다.
그리고 하단의 networks: 부분에 crowdsec이라는 네트워크를 새롭게 추가합니다.
crowdsec:
image: crowdsecurity/crowdsec
container_name: crowdsec
env_file: .env
environment:
- COLLECTIONS=${CROWDSEC_COLLECTIONS}
- GID=${PGID}
depends_on:
traefik:
condition: service_healthy
mariadb:
condition: service_healthy
volumes:
- ${CROWDSEC_PATH}/data:/var/lib/crowdsec/data
- ${CROWDSEC_PATH}/config:/etc/crowdsec
- ${TRAEFIK_PATH}/logs:/logs/traefik:ro
- /var/log:/var/log:ro
networks:
- crowdsec
- web
restart: always
...
networks:
web:
name: web
crowdsec:
name: crowdsec
생성한 crowdsec 네트워크는 MariaDB 컨테이너의 networks: 에도 추가해주면 됩니다.
변경 완료 후 MariaDB와 CrowdSec 서비스를 재시작해서 적용해줍니다.
sudo docker compose restart mariadb
sudo docker compose restart crowdsec
이제 SQLite 대신 MariaDB를 사용해서 데이터를 보관합니다.
SQLite를 계속 사용하려는 경우는 이 단계는 건너뛰면 됩니다.
5. CrowdSec 가입
이제 아래 링크로 접속해서 CrowdSec에 가입합니다.
화면의 Sign up 버튼을 누르고 가입을 하면 됩니다.
사용할 이메일과 비밀번호를 입력해서 계정을 생성하면 됩니다.
입력한 이메일에 확인 메일이 오면 클릭해서 가입을 완료하면 됩니다.
로그인하면 인스턴스를 추가하는 방법을 확인할 수 있습니다.
등록하기 위해 다음 명령어를 실행하면 됩니다.
sudo docker compose exec -t crowdsec cscli console enroll xxxxxxxxxxxxxxxxxxxxxxxxx
enroll 다음의 키는 웹에서 표시된 실제 키를 입력해야 합니다.
인스턴스 등록이 완료되면 다시 웹 브라우저로 이동해서 새로고침 하면 요청이 표시됩니다.
본인이 요청한 내용이 맞는지 확인하고 Accept enroll을 눌러서 등록을 마치면 됩니다.
6. Traefik Bouncer 설치
CrowdSec 설치 후 Bouncer를 설치해야 침입을 방지할 수 있습니다.
여기서는 Traefik Bouncer 설치를 통해 Traefik을 통해 오는 요청들을 필터링하는 방법을 알아보겠습니다.
먼저 다음 명령어로 API 키를 생성합니다.
sudo docker compose exec -t crowdsec cscli bouncers add traefik-bouncer
아래와 같이 생성된 API 키가 화면에 표시됩니다.
생성된 API 키는 다시 확인할 수 없기 때문에 따로 기록해 둡니다.
.env 파일을 열어서 생성된 API를 CROWDSEC_KEY_TRAEFIK의 값으로 입력합니다.
sudo nano ~/.env
API 키를 입력하고 저장한 후에 컨테이너를 시작합니다.
sudo docker compose up -d traefik-bouncer
이제 Traefik에 미들웨어들을 추가합니다.
sudo nano /data/traefik/config/rules/middlewares.toml
기존에 추가되어 있는 basicAuth 하단에 다음과 같은 내용을 추가합니다.
[http.middlewares.rateLimit.rateLimit]
average = 0
burst = 0
[http.middlewares.traefik-bouncer.forwardAuth]
address = "http://traefik-bouncer:8080/api/v1/forwardAuth"
trustForwardHeader = true
[http.middlewares.simpleAuthChain.chain]
middlewares = ["traefik-bouncer", "simpleAuth"]
[http.middlewares.rateLimitChain.chain]
middlewares = ["traefik-bouncer", "redirect-web-to-websecure@internal", "rateLimit"]
Bouncer와 연동할 미들웨어를 추가하고 체인으로 Bouncer 미들웨어가 앞에 위치한 미들웨어들을 추가했습니다.
이제 Traefik이 사용하고 있는 simpleAuth를 변경해 보겠습니다.
sudo nano /data/traefik/config/rules/routers.toml
중간의 middlewares 부분을 다음과 같이 변경합니다.
middlewares = ["simpleAuthChain"]
테스트를 위해 아래 명령어를 실행합니다.
sudo docker logs -f crowdsec
이제 https://traefik.도메인으로 접속해서 로그에 현재 접속 중인 IP가 표시되는지 확인하면 됩니다.
수동으로 IP를 차단하고 싶으면 다음 명령어로 차단할 IP를 추가할 수 있습니다.
sudo docker compose exec -t crowdsec cscli decision add -i IP주소
차단한 IP를 삭제하는 것은 다음 명령어로 가능합니다.
sudo docker compose exec -t crowdsec cscli decision delete -i IP주소
CrowdSec 대시보드의 Alerts에서 다음과 같이 차단된 IP들을 확인할 수 있습니다.
공격이 얼마나 자주 어디에서 들어오는지 파악하는데 도움이 됩니다.
7. 차단 시간 설정
공격이 너무 빈번하다면 차단 시간을 늘리는 방법을 고려할 수 있습니다.
차단 시간 설정은 CrowdSec의 profile.yaml을 통해 변경 가능합니다.
sudo nano /data/crowdsec/config/profiles.yaml
다음 부분을 찾아서 duration의 시간을 변경해 주면 됩니다.
decisions:
- type: ban
duration: 4h
기본값은 4시간인데 원하는 시간만큼의 값을 입력하면 됩니다.
15일 정도 차단을 시키고 싶다면 360h로 입력하면 됩니다.
sudo docker compose restart crowdsec
설정을 완료하고 CrowdSec을 재시작하면 반영됩니다.
CrowdSec은 다양한 곳에서 수집된 IP 리스트를 바탕으로 안전하게 외부에 노출된 서비스들을 보호할 수 있습니다.
다만 CrowdSec은 시스템의 로그 등을 수집할 수 있습니다.
이 부분이 우려가 된다면 CrowdSec을 설치하지 않고 Traefik 만으로 사용해도 됩니다.
이것으로 CrowdSec의 기본적인 설정이 완료됩니다.