Files
obsidian/services/netbis.md
kappa 2356b86d36 obsidian: 정본 문서에서 히스토리/인시던트 분리 완료
15개 정본 문서에서 날짜별 변경이력, 인시던트 기록, 폐기된 구현 상세를
history/ 디렉토리로 분리. 정본은 현재 상태만 기술하는 백서 형태로 정리.
각 정본에 history 위키링크 추가.

분리된 history 파일 12건:
- apisix git push 500, k3s postgresql migration, apisix→traefik 전환
- netbis DDoS 공격, gitea 이전/분리, usb 2.5g hang + NFS hard mount
- supabase→patroni, apisix etcd 통합/분리, anomaly-detect 재설계
- patroni failover incident, zlambda nixos migration, ops-agents setup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 12:09:21 +09:00

11 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 sandbox-tokyo /root/.config/cloudflare/cf-global-api-key
Linode API Key e7cd3103ca76b865df2533b32eee5c8d7799c963fb29848274245dee142d21b0
API Token (바운서용) crowdsec-cf-bouncer-netbis (Workers, Turnstile, WAF, Zone 권한)
Workers 플랜 Paid ($5/월, 1000만 요청 포함)

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 Worker Bouncer (netbis-cf)

항목
컨테이너 jp1 incus netbis-cf-bouncer (10.253.103.33)
바운서 이름 netbis-cf (CrowdSec LAPI 등록)
LAPI 키 FR/PbHA110b6+m/gkByp9itNOaQMdbM8BwKR3DerCTI
설정 파일 /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
동작 CrowdSec ban → Cloudflare Worker + Turnstile captcha
적용 범위 Netbis 계정 전체 6개 zone

기존 cs-cf-worker-bouncer (Kappa 계정용)와 별도 컨테이너로 분리 운영.

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, 재시작 시 초기화 주의)

유사시 전환 절차

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

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

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

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에 등록.