Files
obsidian/services/netbis.md
kaffa e5c6b4deab netbis CF firewall bouncer 재구축 (origin filter) + VL acquisition 통합 + sigmatch v2.4
- crowdsec-safeline.md: VL → CrowdSec acquisition 3개(apisix/traefik/npm) → 1개 통합
  (victorialogs-nginx.yaml, query OR 결합). Netbis NPM CrowdSec 연동 활성.
  netbis-cf-firewall 재구축 섹션 추가.
- services/netbis.md: bouncer 폐기 → 재구축 정정. firewall_bouncer_token 정보 갱신.
  Worker bouncer는 트래픽 비례 비용으로 재구축 안 함 명시.
- history/2026-04-25-netbis-cf-firewall-rebuild.md: 오늘 작업 종합 (sigmatch v2.4
  MP 제거, VL 통합, CrowdSec 연동, CF Firewall bouncer 재구축, origin filter로
  10k 한도 회피).

origin filter [crowdsec, cscli] 적용으로 2026-04-23 폐기 사유였던 CF IP List
10k 한도 회피. Worker bouncer는 origin filter로 회피 불가 (트래픽 비례 비용)
이라 재구축 안 함.
2026-04-25 12:43:47 +09:00

16 KiB
Raw Blame History

title, updated, aliases, tags
title updated aliases tags
Netbis 예비서버 (zlambda) 2026-04-08 APISIX NixOS oci-containers로 재가동
netbis-sandbox-tokyo
netbis
apisix
dr
cloudflare
nixos

개요

Netbis 팀 도메인의 예비(DR) 리버스 프록시 서버. 평소에는 트래픽을 받지 않으며, 유사시 Cloudflare DNS를 수동 전환하여 활성화.

기존 Ironclad 인프라(apisix, crowdsec-safeline)와는 별도 구성.

APISIX/etcd는 NixOS virtualisation.oci-containers로 기동 완료. 설정은 zlambda flake의 apisix.nix 모듈. 라우트/SSL은 비어 있으므로 DR 역할 부트스트랩은 별도 작업 필요.

서버 정보

항목
호스트명 zlambda (구 sandbox-tokyo, 2026-04-08 변경)
Linode 라벨 zlambda (id 47271589)
공인 IP 139.162.71.52
Tailscale IP 100.78.51.18 (2026-04-08 변경, 이전 100.79.87.48)
위치 Linode Tokyo (ap-northeast, lish-tokyo2)
OS NixOS 25.05 (Warbler), x86_64-linux
Linode kernel linode/direct-disk (NixOS 자체 GRUB)
디스크 sda 49.5G ext4 (/), sdb 510M swap
SSH ssh root@zlambda (또는 alias ssh root@sandbox-tokyo, 공인 IP ssh root@139.162.71.52)
LISH 사용자 netbis@lish-tokyo2.linode.com (kaffa-Macmini SSH key)

APISIX 구성

NixOS virtualisation.oci-containers로 선언 — ~/nixos-infra/apisix.nix. 재배포는 nixos-rebuild switch --flake .#zlambda.

컨테이너 이미지 포트
apisix apache/apisix:3.15.0-debian 80(→9080), 443(→9443), 9180
apisix-etcd quay.io/coreos/etcd:v3.5.11 2379 (내부)
  • Docker 네트워크: apisix-net (172.22.222.0/24), etcd=172.22.222.3, apisix=172.22.222.20
  • Admin API: http://127.0.0.1:9180 (admin key 필수, Linode 방화벽이 public 차단 → Tailscale 경유)
  • Admin Key: agenix로 암호화 (secrets/apisix-admin-key.age). activation 시 /run/agenix/apisix-admin-key로 복호화, render 서비스가 /run/apisix/config.yaml에 sed 치환. 회전 시 nix run github:ryantm/agenix -- -e secrets/apisix-admin-key.agenixos-rebuild switch.
  • APISIX 컨테이너 ulimits: nofile 655360
  • 영속 데이터:
    • etcd: bind mount /var/lib/apisix/etcd (root 소유)
    • apisix 로그: docker named volume apisix-logs (이미지 VOLUME 선언이 uid 1001 권한 세팅)
  • config.yaml: 템플릿(Nix store, __ADMIN_KEY__ 자리표시자) → apisix-render-config.service(oneshot)가 /run/apisix/config.yaml에 렌더링 → 컨테이너에 read-only bind mount
  • systemd 의존: init-apisix-net.service(oneshot) → docker-apisix-etcd.service; apisix-render-config.service(oneshot) + init-apisix-net.servicedocker-apisix.service
  • 플러그인: real-ip, cors, ip-restriction, proxy-rewrite, response-rewrite, redirect, limit-*, prometheus, http-logger, file-logger 등 (config.yaml 참조). crowdsec-bouncer 플러그인은 미포함 (커스텀 lua 이전 필요 시 별도 작업).

global_rules

  • real-ip — source: http_cf_connecting_ip, trusted: Cloudflare IP 대역
  • http-logger → CrowdSec http://10.253.100.240:8085/apisix-logs (auth: apisix-crowdsec-log-2024)

커널 튜닝

/etc/sysctl.d/99-apisix-tuning.conf 적용 완료:

  • TCP BBR, conntrack 262144, fin_timeout 10s, keepalive 300s
  • syncookies, netdev_backlog 16384, port range 1024-65535
  • fs.file-max 1048576

Cloudflare 계정 (Netbis)

항목
이메일 netbis@netbis.io
Account ID 8fcf3c7876332aba33e974cbbfdad951
Global API Key Vault secret/cloud/cloudflare-netbis (global_api_key)
Linode API Key e7cd3103ca76b865df2533b32eee5c8d7799c963fb29848274245dee142d21b0
API Token (Worker bouncer용) crowdsec-cf-bouncer-netbis → 2026-04-23 Worker bouncer 폐기 시 token 삭제됨
API Token (Firewall bouncer용) Vault secret/cloud/cloudflare-netbis (firewall_bouncer_token, id firewall_bouncer_token_id). 2026-04-25 발급. 권한: Account Firewall Access Rules Write + Account Rule Lists Write + 6 zone Firewall Services Write
Workers 플랜 Paid ($5/월, 1000만 요청 포함) — 현재 미사용 (Worker bouncer 폐기 후 재구축 안 함)

Zone 목록

Zone Zone ID 플랜 현재 오리진
fall-vip.com 662312b0ca619d1d5c8f4c112150d749 Pro 42.125.196.86
fall-mvp.com 6c171579912a271c0fc89c8187493b0f Free 139.162.73.240
fall-vip7.com a8832b9d3b546f96505abeadea4750d1 Free 139.162.73.240
psd777.com a14533c2937b19e5b7ed19cbecd58679 Pro 139.162.114.197
rss-555.com 6d4b084940520c1f820927e5d8ade2c6 Pro 139.162.73.17
rss-7790.com d9db9e50e202339326498baa340a9d16 Pro 139.162.73.17

모든 zone은 Cloudflare Flexible SSL, 프록시(오렌지 구름) 사용.

라우트 및 업스트림

라우트 ID 호스트 업스트림 (오리진 IP)
fall-vip-com fall-vip.com 42.125.196.86
fall-mvp-com fall-mvp.com 139.162.73.240
fall-vip7-com fall-vip7.com 139.162.73.240
psd777-com psd777.com 139.162.114.197
rss-555-com rss-555.com 139.162.73.17
rss-7790-com rss-7790.com 139.162.73.17
ev-fall-vip-com ev.fall-vip.com 42.125.196.115
ev-fall-vip7-com ev.fall-vip7.com 42.125.196.115
ev-psd777-com ev.psd777.com 42.125.196.115
vi-rss-555-com vi.rss-555.com 42.125.196.115
vi-rss-7790-com vi.rss-7790.com 42.125.196.115

모든 라우트에 proxy-rewrite (Host 전달) 적용.

SSL 인증서

acme.sh + Cloudflare DNS-01 챌린지로 발급. 크론 자동 갱신.

도메인 SAN 발급기관 만료
fall-vip.com *.fall-vip.com ZeroSSL 2026-07-02
fall-mvp.com *.fall-mvp.com ZeroSSL 2026-07-02
fall-vip7.com *.fall-vip7.com ZeroSSL 2026-07-02
psd777.com *.psd777.com ZeroSSL 2026-07-02
rss-555.com *.rss-555.com ZeroSSL 2026-07-02
rss-7790.com *.rss-7790.com ZeroSSL 2026-07-02

인증서 경로: /root/.acme.sh/{domain}_ecc/

CrowdSec 연동

http-logger

APISIX global_rule로 모든 요청 로그를 CrowdSec(jp1)로 전송.

  • 엔드포인트: http://10.253.100.240:8085/apisix-logs
  • 인증: auth_header: apisix-crowdsec-log-2024
  • 파서: custom/apisix-json-logs (기존 파서 공유)

Cloudflare Firewall Bouncer 재구축 (2026-04-25)

2026-04-23에 두 종류 bouncer (Worker + Firewall Rule) 모두 폐기됐다가 (../history/2026-04-23-netbis-bouncer-removal), 2026-04-25에 Firewall Rule bouncer만 재구축.

항목
컨테이너 jp1 incus crowdsec (LAPI와 동거. 별도 컨테이너 X)
패키지 crowdsec-cloudflare-bouncer 0.3.0 (apt)
LAPI bouncer 이름 cs-cloudflare-bouncer-1777082222 (자동 생성)
설정 파일 /etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml
origin filter [crowdsec, cscli] — CAPI 30k+/lists 무시 (10k 한도 회피 핵심)
적용 범위 netbis 계정 전체 6개 zone, managed_challenge 액션
CF 리소스 IP List crowdsec_managed_challenge + 6 Zone Firewall Rule 자동 생성
API token Vault secret/cloud/cloudflare-netbisfirewall_bouncer_token, firewall_bouncer_token_id
Token 권한 Account Firewall Access Rules Write, Account Rule Lists Write, 6 zone Firewall Services Write
인증 방식 Bearer token. global_api_key는 Invalid request headers (6003)로 거부
비용 $0 (Free plan IP List + Firewall Rule 사용)

2026-04-23에 Worker Bouncer (netbis-cf) 도 폐기됐고 2026-04-25 재구축에는 포함 안 됨 — Worker는 트래픽 비례 비용($14~50/월 추정)이라 origin filter로 회피 불가.

상세 history: ../history/2026-04-25-netbis-cf-firewall-rebuild

Cloudflare 보안 설정

Rate Limiting (120/분)

Zone 제한 액션 차단시간
fall-vip.com 120/분 managed_challenge 60초
psd777.com 120/분 managed_challenge 60초
rss-555.com 120/분 managed_challenge 60초
rss-7790.com 120/분 managed_challenge 60초
fall-mvp.com 20/10초 (~120/분) block (Free 제한) 10초
fall-vip7.com 20/10초 (~120/분) block (Free 제한) 10초

정상 사용자 IP당 ~10 req/분 기준, 12배 여유. 공격 IP(230+/분)는 확실히 차단.

Super Bot Fight Mode

Pro zone 4개(fall-vip.com, psd777.com, rss-555.com, rss-7790.com)에 적용:

  • Definitely automated → managed_challenge
  • Verified bots → allow
  • Static resource protection → true

Free zone(fall-mvp.com, fall-vip7.com)은 미적용.

DDoS Protection

기본 활성화 상태 (Cloudflare managed ruleset). 감도는 기본값(Medium).

트래픽 기준

일 평균 약 140만 요청. 월 환산 약 4200만.

공격 이력: ../history/2026-03-31-netbis-ddos-attack

로그 분석

사용 가능

  • CF GraphQL Analytics API — 시간별/국가별/threat 데이터 조회 (보관 30일)
  • APISIX http-logger → CrowdSec — 오리진 도달 요청 분석

Logpush (Enterprise 전용, 현재 불가)

Cloudflare Logpush(HTTP 요청 로그를 R2 등으로 전송)는 Enterprise 플랜 전용. Pro 플랜에서는 사용 불가.

Workers Logpush (준비만 완료)

Workers Paid에 포함. CrowdSec Worker Bouncer 요청 로그를 R2에 저장 가능.

  • R2 버킷 cf-logs 생성 완료 (APAC region)
  • R2 API Token: r2-logpush-cf-logs (id: 6450de0b6fc95f6d47affa8be3804a75)
  • 비용: 월 2000만 건 포함, 초과분 $0.60/100만 건
  • 정상 트래픽 기준 약 $13/월 추가 발생 예상
  • 공격 시 비용 폭증 가능 → 필요 시에만 활성화 권장, 현재 미활성

Workers 비용 예상

시나리오 월 요청 Workers 비용
정상 ~4200만 ~$14.6
폭주 포함 ~1.6억 ~$50
Rate Limit 적용 후 정상 ~4200만 ~$14.6
Rate Limit 적용 후 폭주 대폭 감소 예상 ~$15-20

NPM 서버 (오리진)

호스트명 IP 비고
NPM-1 172.104.100.11
NPM-2 139.162.114.197 SSH 비밀번호 인증 → 키 등록 완료
NPM-3 139.162.73.17 rss-555.com, rss-7790.com 오리진
NPM-4 139.162.73.240 fall-vip.com, fall-mvp.com, fall-vip7.com 오리진
NPM-5 172.104.70.137
npm-6 172.105.226.218

6대 모두 커널 튜닝 완료 (/etc/sysctl.d/99-proxy-tuning.conf):

  • TCP BBR, conntrack 262144, fin_timeout 10s, keepalive 300s, port range 1024-65535
  • limits.conf nofile 655360 (Docker 컨테이너 반영은 compose ulimits 추가 필요, 서비스 중이라 미적용)

NPM-4 추가 튜닝

  • 커널: tcp_tw_reuse=1, rmem_max/wmem_max 16MB, tcp_max_tw_buckets 131072, tcp_max_orphans 32768
  • Nginx: worker_connections 10240, proxy_buffers 16 32k, keepalive_requests 1000, open_file_cache
  • real_ip_header: CF-Connecting-IP (컨테이너 내 sed, 재시작 시 초기화 주의)

로그 수집 (Vector → zlambda → VictoriaLogs)

6대 모두 호스트-레벨 Vector 0.55 가 NPM 로그 파일을 tail → zlambda(vector-relay 0.45, 컨테이너) → VictoriaLogs(vl.inouter.com). 2026-04-23 구축.

NPM-1..6 호스트 Vector(0.55)
  source: file tail /root/data/logs/proxy-host-*_access.log 등 (NPM-6만 /home/kaffa/npm/data/log/)
  transform: remap (VRL, NPM proxy/standard log 포맷 파싱 → ip/method/path/status/bytes/user_agent/referer/domain/upstream)
  sink: http POST http://139.162.71.52:9999/ (zlambda public IP) basic auth (user=npm-relay, password=zlambda agenix bearer)
    └─ zlambda Vector-relay(0.45, Docker, net vector-net)
        source: http_server 0.0.0.0:9999 basic auth
        transform: remap — `.relay = "zlambda"` 태그
        sink: elasticsearch bulk https://vl.inouter.com/insert/elasticsearch
             └─ VictoriaLogs (index `npm-netbis`, stream fields: host, service, log_type)
항목
NPM Vector 설치 sh.vector.dev 공식 스크립트 → /usr/local/bin/vector, systemd unit vector.service
NPM Vector 설정 /etc/vector/vector.yaml (mode 600, bearer 평문 포함), checkpoints /var/lib/vector/npm_{access,error}/
라벨 host=npm-1..6, service=npm, `log_type=access
파싱 포맷 NPM proxy/standard v2 (Real+XFF 포함, 2026-04-23 이후) 우선, v1(Real+XFF 없음) legacy fallback. 모두 실패 시 log_format=raw
nginx 설정 6대 전부 real_ip_header CF-Connecting-IP, real_ip_recursive on, set_real_ip_from 에 CF + CloudFront IP 대역 포함. log_format에 [Client $remote_addr] [Real $realip_remote_addr] [XFF $http_x_forwarded_for] 3필드 기록 (2026-04-23 일괄 패치)
client_ip 의미 nginx real_ip 재작성 후의 실 고객 IP (CF-Connecting-IP 경유). IPv6 방문자는 CF Pseudo IPv4 기능으로 240.0.0.0/4 (240~255.x.x.x) 범위의 해시 값으로 나타남../infra/security/cloudflare#Pseudo IPv4 (Class E 240/4) 참조. Rewrite 실패(Client == Real) 시 client_ip_is_cf_edge=true + client_ip=null + client_ip_source=cf_edge_rewrite_failed
zlambda relay zlambda NixOS container vector-relay (Docker timberio/vector:0.45.0-debian, net vector-net, port 9999/tcp)
zlambda 모듈 ~/nixos-infra/vector.nix — 전용 render/env systemd + Docker oci-container
bearer token zlambda agenix secrets/vector-bearer-token.age (kaffa + zlambda host key 복호화). NPM config 에는 평문, Vault 백업은 secret/cloud/vector-relay-netbis
Linode 방화벽 (zlambda 691875) inbound allow TCP 9999 from 6 NPM /32 IPs (allow-npm-relay-9999 rule)
VL 샘플 쿼리 service:npm host:"npm-4" / service:npm zone:"fall-vip.com" / service:npm log_type:error
로그 이력 [[../history/2026-04-23-netbis-npm-vl-collection

유사시 전환 절차

  1. Cloudflare DNS에서 각 도메인 A 레코드를 139.162.71.52로 변경 (수동)
  2. APISIX 라우트/SSL 사전 등록 완료 상태이므로 즉시 서비스 가능
  3. 전환 후 CrowdSec 로그 수신 및 바운서 차단 자동 동작 확인

이전 서비스 제거 이력: ../history/2026-04-08-zlambda-nixos-migration

보안 방어 개발 중

  • ../projects/netbis-sigmatch — VL 로그 기반 자동 시그니처 합성 + CF IP Access Rules 차단 (개발 단계, kappa 직접 진행)

부트스트랩 체크리스트 (재가동 시)

DR 활성화 전에 필요한 작업:

  • Linode 방화벽/네트워크: Cloudflare IP 대역이 80/443에 도달하는지 확인
  • acme.sh 재설치 (NixOS 환경에서 services.acme 또는 docker로 별도 실행). 기존 cert 경로 /root/.acme.sh/{domain}_ecc/는 삭제됨
  • 6개 도메인 × wildcard cert 재발급 (ZeroSSL, Cloudflare DNS-01)
  • admin API로 11개 라우트 + 업스트림 + SSL 등록 (위 "라우트 및 업스트림" 표 참고)
  • global_rules: real-ip(Cloudflare IPs) + http-logger(CrowdSec jp1 10.253.100.240)
  • CrowdSec LAPI 키 재확인 — netbis 전용 바운서용 (vault에 저장)
  • Cloudflare DNS 전환 (각 zone A 레코드 → 139.162.71.52)

crowdsec-bouncer 플러그인이 필요하면 osaka에서 crowdsec-bouncer.lua 파일 가져와 apisix.nix 볼륨에 추가하고 config.yaml plugins에 등록.