본문 바로가기
서버구축 (WEB,DB)

Nginx Plus API 및 Ingress 기반 동적(Dynamic) IP ACL 구현

by 날으는물고기 2024. 8. 27.

Nginx Plus API 및 Ingress 기반 동적(Dynamic) IP ACL 구현

NGINX Plus를 사용하여 동적 IP ACL(Access Control List)을 관리하는 방법입니다.

1. 개요

NGINX Plus의 동적 IP ACL 관리는 특정 클라이언트 IP 주소에 대한 접근을 제어하기 위해 동적 denylist(차단 목록)와 allowlist(허용 목록)를 생성하고 관리할 수 있는 기능을 제공합니다. 이 기능은 NGINX Plus Release 13부터 제공되며, Release 19에서는 네트워크 범위 내의 IP 주소와 서브넷을 지원하는 기능이 추가되었습니다.

2. 사전 준비 사항

  • NGINX Plus Release 13 이상이 필요합니다.
  • 네트워크 범위 지원을 위해 NGINX Plus Release 19 이상이 필요합니다.

3. 설정 단계

3.1 메모리 영역 설정

먼저, denylist와 allowlist를 저장할 메모리 영역을 설정해야 합니다. NGINX Plus 설정 파일의 http 컨텍스트에 keyval_zone 지시어를 추가하여 키와 값을 저장할 메모리 영역을 만듭니다.

http {
    # 1MB 메모리 영역 생성
    keyval_zone zone=one:1m;
}

3.2 서브넷 매칭 설정

IP 주소를 서브넷과 매칭하려면 keyval_zone 지시어에 type=ip 파라미터를 추가합니다. 이 경우, 메모리 영역 크기를 추가 인덱스 저장을 위해 적절히 증가시켜야 합니다.

http {
    keyval_zone zone=one:1m type=ip;
}

3.3 영속적인 데이터 저장 설정

keyval_zonestate 파라미터를 추가하여 데이터를 파일에 저장하고, NGINX Plus의 리로드 및 재시작 시에도 데이터가 유지되도록 설정할 수 있습니다.

keyval_zone zone=one:1m state=one.keyval;

3.4 NGINX Plus API 활성화

이제 NGINX Plus API를 활성화하여 키-값 데이터베이스를 동적으로 관리할 수 있도록 합니다. API는 읽기 및 쓰기 모드로 설정합니다.

server {
    listen 80;
    server_name www.example.com;

    location /api {
        api write=on;

        # 로컬호스트만 접근 허용
        allow 127.0.0.1;
        deny all;

        # PATCH, POST, DELETE 메서드 제한
        limit_except GET {
            auth_basic "NGINX Plus API";
            auth_basic_user_file /path/to/passwd/file;
        }
    }
}

4. 키-값 데이터베이스에 IP 주소 추가

4.1 IP 주소 추가

다음 curl 명령을 사용하여 keyval 데이터베이스에 IP 주소를 추가합니다. 여기서 1은 denylist, 0은 allowlist를 나타냅니다.

curl -X POST -d '{
    "10.0.0.1": "1",
    "10.0.0.2": "1",
    "10.0.0.3": "0",
    "10.0.0.4": "0"
}' -s http://www.example.com/api/6/http/keyvals/one

4.2 서브넷 범위 추가

서브넷 범위로 IP 주소를 추가하려면 CIDR 표기법을 사용합니다.

curl -X POST -d '{
    "192.168.13.0/24": "1"
}' -s http://www.example.com/api/6/http/keyvals/one

5. 클라이언트 IP 주소 평가 및 액세스 제어 설정

5.1 IP 주소 평가

NGINX Plus가 각 요청을 처리할 때 클라이언트의 IP 주소를 keyval 데이터베이스와 비교하여 결과를 $target 변수에 저장합니다.

http {
    keyval_zone zone=one:1m type=ip state=one.keyval;
    keyval $remote_addr $target zone=one;
}

5.2 액세스 제어

클라이언트 IP 주소가 denylist에 있는 경우 403(Forbidden) 응답을 반환하도록 설정합니다.

server {
    if ($target) {
        return 403;
    }
}

6. 키-값 데이터베이스 관리

6.1 데이터베이스 조회

현재 데이터베이스에 저장된 모든 항목을 조회하려면 다음 명령을 사용합니다.

curl -X GET 'http://www.example.com/api/6/http/keyvals/one'

6.2 데이터베이스 업데이트

기존 항목을 업데이트하려면 PATCH 메서드를 사용합니다.

curl -X PATCH -d '{"10.0.0.4": "1"}' -s 'http://www.example.com/api/6/http/keyvals/one'

6.3 항목 추가

데이터베이스에 새로운 항목을 추가하려면 다음 명령을 사용합니다.

curl -X POST -d '{"10.0.0.5": "1"}' -s 'http://www.example.com/api/6/http/keyvals/one'

6.4 항목 삭제

기존 항목을 삭제하려면 PATCH 메서드를 사용하여 값을 null로 설정합니다.

curl -X PATCH -d '{"10.0.0.4":null}' -s 'http://www.example.com/api/6/http/keyvals/one'

7. 전체 설정 예제

위에서 설명한 설정을 종합한 전체 NGINX Plus 설정 예제입니다.

http {
    keyval_zone zone=one:1m type=ip state=one.keyval;
    keyval $remote_addr $target zone=one;

    server {
        listen 80;
        server_name www.example.com;

        location /api {
            api write=on;

            allow 127.0.0.1;
            deny all;

            limit_except GET {
                auth_basic "NGINX Plus API";
                auth_basic_user_file /path/to/passwd/file;
            }
        }

        if ($target) {
            return 403;
        }
    }
}

이 설정은 1MB의 메모리 영역을 생성하고, IP 주소에 대한 denylist와 allowlist를 동적으로 관리할 수 있도록 구성합니다. 이를 통해 관리자는 NGINX Plus API를 사용하여 실시간으로 IP 주소 목록을 업데이트하고, 클라이언트의 접근을 제어할 수 있습니다.

NGINX Plus와 fail2ban을 이용한 동적 차단 구현 예제

NGINX Plus와 fail2ban을 사용하여 웹 애플리케이션에 대한 악성 활동을 동적으로 차단하는 방법입니다. 브루트 포스 공격, 스팸 봇, 그리고 기타 의심스러운 활동을 감지하고 해당 IP 주소를 자동으로 차단하는 데 유용합니다. 특히, NGINX Plus의 Key-Value Store 기능과 API를 활용하여 fail2ban에서 감지된 악성 IP를 실시간으로 차단하는 방식으로 구현됩니다.

1. fail2ban이란?

fail2ban은 로그 파일을 지속적으로 모니터링하여 특정 패턴(예: 로그인 실패)을 감지하고, 의심스러운 IP 주소를 자동으로 방화벽 규칙에 추가하여 일정 기간 동안 차단(ban)하는 침입 탐지 시스템(IDS)입니다. 서버 보안을 강화하는 데 자주 사용되며, NGINX Plus와 결합하여 동적으로 악성 IP를 차단하는 데 매우 효과적입니다.

2. NGINX Plus의 Key-Value Store를 활용한 동적 차단

Key-Value Store는 NGINX Plus에서 제공하는 인메모리 데이터 저장소로, API를 통해 동적으로 IP 주소를 관리할 수 있습니다. Key-Value Store는 NGINX Plus의 설정 파일이나 재시작 없이도 실시간으로 구성 변경이 가능하여, fail2ban과 같은 외부 시스템이 NGINX Plus의 동작을 제어할 수 있습니다.

 

Key-Value Store 설정

keyval_zone zone=denylist:1M state=denylist.json;
keyval $remote_addr $num_failures zone=denylist;

server {
    listen 80;

    location / {
        root /usr/share/nginx/html;

        if ($num_failures) {
            return 403;
        }
    }
}
  • keyval_zone 지시어는 공유 메모리 영역을 설정하며, 여기서 동적으로 관리할 Key-Value 쌍을 저장합니다.
  • $remote_addr 변수는 클라이언트의 IP 주소를 나타내며, 이를 Key-Value Store에서 키로 사용하여 차단된 IP를 확인합니다.
  • $num_failures 변수는 IP가 차단된 경우 403 Forbidden 응답을 반환합니다.

3. fail2ban을 사용한 동적 차단 관리

fail2ban은 NGINX 로그 파일을 모니터링하여, 의심스러운 활동(예: 연속적인 로그인 실패)을 감지하면, 해당 IP 주소를 NGINX Plus의 Key-Value Store에 추가하여 차단합니다.

 

fail2ban 설정 파일 예제 /etc/fail2ban/action.d/nginx-plus-denylist.conf

[Definition]
actionban = curl -s -o /dev/null -d '{"<ip>":"1"}' http://localhost:1111/api/6/http/keyvals/denylist
actionunban = curl -s -o /dev/null -X PATCH -d '{"<ip>":null}' http://localhost:1111/api/6/http/keyvals/denylist
  • actionban은 문제가 되는 IP를 NGINX Plus의 denylist에 추가합니다.
  • actionunban은 차단된 IP를 해제합니다.

 

fail2ban jail 설정 /etc/fail2ban/jail.local

[nginx-http-auth]
enabled  = true
filter   = nginx-http-auth
action   = nginx-plus-denylist
logpath  = /var/log/nginx/access.log
bantime  = 600
findtime = 600
maxretry = 3
  • nginx-http-auth jail은 NGINX의 HTTP 기본 인증 실패를 감지합니다.
  • bantime은 IP가 차단되는 시간을 설정합니다(여기서는 10분).
  • maxretry는 허용된 로그인 시도 횟수를 정의합니다(여기서는 3회).

4. NGINX Plus 설정과 fail2ban 통합

fail2ban이 로그 파일에서 여러 번의 인증 실패를 감지하면, NGINX Plus의 Key-Value Store를 통해 해당 IP를 차단하고, 요청을 403 Forbidden으로 응답합니다. 이때, fail2ban은 차단된 IP에 대한 설정을 NGINX Plus API를 통해 관리하므로, 설정 파일을 재로드할 필요 없이 실시간으로 IP를 차단하거나 해제할 수 있습니다.

 

NGINX Plus와 fail2ban을 사용한 동적 IP 차단 솔루션은 웹 애플리케이션의 보안을 강화하고, 브루트 포스 공격과 같은 악성 행위로부터 보호할 수 있습니다. NGINX Plus의 Key-Value Store와 API를 활용하여 실시간으로 악성 IP를 관리하며, fail2ban은 로그 파일을 지속적으로 모니터링하여 의심스러운 활동을 감지하고 대응합니다. 이러한 다층적 보안 접근법은 웹 애플리케이션을 보다 안전하게 보호하는 데 매우 효과적입니다.

Nginx Ingress를 통해 내부 시스템 접근을 허용하면서, URL 별로 IP 기반 ACL(Access Control List)을 동적으로 운영하는 방식에 대해 설명드리겠습니다. 이를 위해 몇 가지 기술과 도구를 활용할 수 있습니다.

1. 개요 및 배경정보

Nginx Ingress Controller는 Kubernetes 환경에서 많이 사용되는 도구로, 외부 트래픽을 내부 서비스로 라우팅하는 역할을 합니다. 기본적으로 정적 설정을 통해 동작하지만, 동적으로 설정을 변경할 수 있는 방법도 존재합니다.

2. 동적 URL 별 IP 기반 ACL 운영 방식

동적 IP 기반 ACL을 운영하기 위해서는 다음과 같은 방법들을 고려할 수 있습니다:

a. ConfigMap을 활용한 설정

Kubernetes의 ConfigMap을 활용하여 Nginx Ingress의 설정을 동적으로 관리할 수 있습니다. 이는 간단하지만 ConfigMap 변경 후 Ingress Controller를 다시 로드해야 하는 단점이 있습니다.

b. Lua 스크립트를 이용한 동적 설정

Nginx는 Lua 스크립트를 통해 동적으로 설정을 변경할 수 있는 기능을 제공합니다. 이를 통해 특정 URL에 대한 IP 기반 ACL을 동적으로 관리할 수 있습니다.

c. Nginx Ingress Controller의 Annotation 기능

Nginx Ingress Controller는 Annotation을 통해 특정 설정을 추가할 수 있습니다. 이를 활용하여 특정 URL에 대한 IP 기반 ACL을 설정할 수 있습니다.

3. 구체적인 구현 방법

a. ConfigMap을 이용한 구현

ConfigMap을 사용하여 Nginx Ingress의 설정을 관리하는 방법입니다. 예시로 ConfigMap을 생성하고 적용하는 방법을 보여드리겠습니다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-ingress-config
  namespace: ingress-nginx
data:
  allowlist-source-range: "192.168.1.0/24, 10.0.0.0/8"

이 ConfigMap을 Nginx Ingress Controller에 적용하는 방법은 다음과 같습니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/configuration-snippet: |
      allow 192.168.1.0/24;
      allow 10.0.0.0/8;
      deny all;
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: example-service
            port:
              number: 80

b. Lua 스크립트를 이용한 동적 설정

Nginx에서 Lua 모듈을 활용하여 동적으로 IP 기반 ACL을 설정하는 방법입니다. Lua 스크립트를 사용하여 동적으로 IP를 허용하거나 차단할 수 있습니다.

http {
    lua_shared_dict allowed_ips 10m;

    init_by_lua_block {
        local allowed_ips = ngx.shared.allowed_ips
        allowed_ips:set("192.168.1.1", true)
        allowed_ips:set("10.0.0.1", true)
    }

    server {
        location / {
            access_by_lua_block {
                local allowed_ips = ngx.shared.allowed_ips
                local client_ip = ngx.var.remote_addr
                if not allowed_ips:get(client_ip) then
                    ngx.exit(ngx.HTTP_FORBIDDEN)
                end
            }
        }
    }
}

c. Nginx Ingress Controller의 Annotation 기능

Nginx Ingress Controller에서 Annotation을 통해 특정 URL에 대한 설정을 추가할 수 있습니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/whitelist-source-range: "192.168.1.0/24,10.0.0.0/8"
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: example-service
            port:
              number: 80

4. 활용사례 및 추가 정보

  • 자동화: 동적 설정을 위해 CI/CD 파이프라인에서 ConfigMap이나 Lua 스크립트를 자동으로 업데이트하고 Nginx를 다시 로드하는 방법을 적용할 수 있습니다.
  • 보안 강화: 동적 ACL 관리를 통해 보안 정책을 유연하게 적용하고, 특정 IP에서의 접근을 실시간으로 차단할 수 있습니다.
  • 모니터링: 동적 ACL 변경 내역을 로그로 기록하고, 모니터링 시스템과 연계하여 실시간으로 변경 상황을 추적할 수 있습니다.

 

이와 같은 방법들을 활용하여 Nginx Ingress Controller를 통해 URL 별로 동적인 IP 기반 ACL을 효과적으로 관리할 수 있습니다. 모니터링 시스템과 연계되어 자동화된 형태로 ACL IP가 동적으로 운영될 수 있는 구조를 구현하기 위해서는 다음과 같은 아키텍처와 워크플로우를 고려할 수 있습니다.

1. 아키텍처 개요

a. 주요 구성 요소

  1. 모니터링 시스템: Prometheus, ELK Stack (Elasticsearch, Logstash, Kibana), Grafana 등
  2. 자동화 및 스크립트 실행: n8n, Jenkins, GitHub Actions, 또는 자체 개발된 스크립트
  3. Nginx Ingress Controller: Kubernetes 클러스터 내에서 동작하는 Ingress Controller
  4. Configuration Management: ConfigMap, Lua 스크립트, 또는 Annotation을 통한 설정 관리

b. 동작 방식

  1. 로그 수집 및 분석: 모니터링 시스템이 서버에서 발생하는 로그와 이벤트를 수집하고 분석
  2. 조건 감지 및 알림: 특정 조건(예: 비정상적인 트래픽, 보안 위협)을 감지하고 자동화 시스템에 알림
  3. 자동화 시스템: 알림을 받아 IP 차단 또는 허용 등 ACL 변경 작업 수행
  4. Nginx Ingress Controller 업데이트: ConfigMap, Lua 스크립트, 또는 Annotation을 통해 Nginx 설정 업데이트
  5. 모니터링 및 검증: 변경 사항 적용 후 정상 동작 여부를 모니터링 시스템을 통해 검증

2. 구체적인 워크플로우

a. 로그 수집 및 분석

  • Prometheus: 애플리케이션 메트릭 수집 및 분석
  • ELK Stack: 로그 데이터를 수집하고 Kibana를 통해 시각화
# 예시: Filebeat를 이용한 로그 수집 설정
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/nginx/*.log

output.elasticsearch:
  hosts: ["http://elasticsearch:9200"]

b. 조건 감지 및 알림

  • Prometheus Alertmanager: 조건 감지 및 알림 전송
  • Kibana: Watcher를 통해 특정 조건에 대한 알림 설정
# 예시: Prometheus Alertmanager 설정
groups:
- name: example-alert
  rules:
  - alert: HighTraffic
    expr: sum(rate(http_requests_total[5m])) by (job) > 100
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "High traffic detected"
      description: "More than 100 requests per second"

c. 자동화 시스템

  • n8n: 웹훅을 통해 자동화 워크플로우 트리거
  • Jenkins: CI/CD 파이프라인에서 스크립트 실행
# 예시: n8n 워크플로우 설정
{
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "webhook-path",
        "options": {}
      },
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "url": "http://kubernetes-api-server",
        "method": "PATCH",
        "authentication": "headerAuth",
        "jsonParameters": true,
        "bodyParametersJson": "{ \"metadata\": { \"annotations\": { \"nginx.ingress.kubernetes.io/whitelist-source-range\": \"192.168.1.0/24,10.0.0.0/8\" } } }"
      },
      "name": "Update Ingress",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        450,
        300
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Update Ingress",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

d. Nginx Ingress Controller 업데이트

  • ConfigMap: 설정 변경 후 적용
  • Lua 스크립트: 동적으로 IP 차단/허용
  • Annotation: Ingress 리소스 업데이트
# 예시: Ingress 리소스 업데이트
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/whitelist-source-range: "192.168.1.0/24,10.0.0.0/8"
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: example-service
            port:
              number: 80

e. 모니터링 및 검증

  • Prometheus: 설정 변경 후 모니터링
  • Grafana: 대시보드를 통해 실시간 상태 확인
# 예시: Grafana 대시보드 설정
{
  "dashboard": {
    "title": "Nginx Ingress Monitoring",
    "panels": [
      {
        "type": "graph",
        "title": "Requests per second",
        "targets": [
          {
            "expr": "rate(http_requests_total[1m])",
            "legendFormat": "{{job}}"
          }
        ]
      }
    ]
  }
}

3. 사례 및 추가 정보

  • 자동화된 보안 대응: 비정상적인 트래픽이 감지되면 자동으로 해당 IP를 차단하여 보안 위협을 실시간으로 대응
  • 유연한 설정 관리: 동적으로 IP 기반 ACL을 변경하여 보안 정책을 빠르게 적용 및 변경
  • 실시간 모니터링: 설정 변경 후 실시간으로 모니터링하여 정상 동작 여부 확인

 

이와 같은 구조를 통해 모니터링 시스템과 연계된 자동화된 ACL IP 관리 시스템을 구축할 수 있습니다.

워크플로우 설명

  1. Monitoring System: 로그 수집 및 분석을 통해 특정 조건을 감지하고 알림을 전송합니다.
    • 로그 수집 (Log Collection)
    • 로그 분석 (Log Analysis)
    • 조건 감지 (Condition Detection)
    • 알림 전송 (Alert Sending)
  2. Automation System: 알림을 받아 워크플로우를 트리거하고 ACL 업데이트 스크립트를 실행합니다.
    • 알림 수신 및 워크플로우 트리거 (Receive Alert/Trigger Workflow)
    • ACL 업데이트 스크립트 실행 (Execute ACL Update Script)
  3. Configuration Management: ConfigMap, Lua 스크립트 또는 Annotation을 통해 새로운 ACL로 구성 업데이트를 수행합니다.
    • 새로운 ACL로 CM 업데이트 (Update CM with New ACL)
  4. Nginx Ingress Controller: 업데이트된 구성을 적용합니다.
    • 구성 적용 (Apply Updated Configuration)
  5. Continuous Monitoring: 구성 변경 후 지속적으로 모니터링하고 검증합니다.
    • 구성 변경 검증 (Verify Configuration Change)
728x90

댓글