macOS에서 OpenClaw 게이트웨이가 Slack·GitHub 등의 콜백을 받을 때 2026년에 가장 먼저 불타는 지점은 모델 지연이 아니라 서명 검증 불일치입니다. 미들웨어가 JSON.parse 후 다시 문자열로 만들면 공백·키 순서가 달라져 X-Hub-Signature-256이 영원히 맞지 않습니다. 반대로 서명은 통과하지만 리플레이 방어가 없으면 공급자 재시도가 동일 HTML 배포를 두 번 실행합니다. 이 글은 raw body에 대한 HMAC, 감사 가능한 초 단위 리플레이 허용, NTP 오차와 Slack 타임스탬프의 결합, 멱등 키와 중복 제거까지 한 흐름으로 정리합니다. 함께 읽으면 좋은 문서는 Webhook→Ollama 배선, doctor 진단, NTP·JWT 스큐입니다.
실무 숫자로는 채팅 계열은 우선 300초, 지연 재전송이 잦은 GitHub류는 600초를 1차 후보로 잡고 측정된 p95 배달 지연으로 조정하십시오. 프로덕션과 같은 launchd 동작이 필요하면 MacHTML 공개 가격대에서 대략 하루 16.9달러 전후의 Apple Silicon Mac mini를 스테이징 전용으로 두면 노트북 절전 정책과 분리된 야간 리허설이 가능합니다.
위협 모델
OpenClaw가 저장소 쓰기·빌드 트리거까지 맡으면 인증되지 않은 POST는 공급망 공격면이 됩니다. 서명은 필수이나 비밀 유출에는 무력하므로 비밀 순환·최소 권한 도구·IP 제한을 병행하십시오. 외부 스캐너, 사고 조사 중 정당 트래픽 재생, 침해된 상류 재전송을 가정하고 배송 ID를 감사 로그에 남깁니다.
브라우저 CORS 트래픽과 웹훅을 같은 포트에 섞지 마십시오. 별도 서브도메인에 mTLS를 얹으면 운영 비용은 오르나 허용되는 조직도 늘고 있습니다.
raw body와 JSON 순서
알고리즘은 바이트열에 정의됩니다. rawBody를 노출하고 검증 후에만 JSON.parse 하십시오. nginx에서 본문을 변형하는 모듈이 없는지도 확인합니다. 이중 gzip이 있으면 해시 대상 바이트가 GitHub 측과 달라집니다.
로그에는 전체 본문 대신 길이와 해시 지문만 남기고 고객 HTML을 평문으로보내지 않습니다.
GitHub / Slack / 일반 HMAC
GitHub는 X-Hub-Signature-256에 sha256= 접두가 붙은 16진을 실습니다. X-GitHub-Delivery를 멱등 키로 쓰면 재전송 흡수가 쉽습니다. Slack은 v0:{timestamp}:{body}를 HMAC하고 Base64로 X-Slack-Signature에 담습니다. 타임스탬프 검증이 빡세므로 호스트 시계와 강하게 결합합니다. 자체 연동에서는 약한 다이제스트를 거부하는 화이트리스트를 설정합니다.
리플레이 매트릭스
| 소스 | 초기값 | 메모 |
|---|---|---|
| Slack Events | 300초 | NTP 모니터링과 세트 |
| GitHub | 600초 | Delivery ID로 중복 제거 |
| 내부 잡 | 120초 | 저지연 LAN |
| SLA 불명 SaaS | 900초 | Redis 메모리 주의 |
proxy_read_timeout이 120초인데 리플레이 허용만 300초이면 파트너는 재시도 루프에 빠지기 쉽습니다. 초 단위 표를 단일 진실 공급원으로 공개하십시오.
시계 오차
Slack 서명은 몇 분만 어긋나도 실패합니다. Mac mini에서 2초를 넘는 오프셋이 연속이면 알람을 권장합니다. 자세한 내용은 NTP 글을 참고하십시오. 노트북 절전과 상시 전원 미니는 동작이 다릅니다.
Redis TTL
SET NX EX로 배송 지문을 저장하고 TTL은 리플레이 허용과 공급자 재시도 정책 중 큰 값에 맞춥니다. 멱등 글의 TTL 논의와 맞추십시오. 백만 키×백 바이트는 대략 100MB 이상의 압력이 될 수 있습니다.
nginx와 TLS 종단
TLS를 nginx에서 종단하고 127.0.0.1:8787로 중계할 때 웹훅 위치에 불필요한 본문 변환을 걸지 마십시오. client_max_body_size를 여유 있게 잡고 합성 헬스체크와 속도 제한을 분리합니다.
curl 프로브
비공개 저장소에 픽스처를 두고 curl --data-binary @file로 재현합니다. 정상·변조·만료의 세 파동을 반드시 돌리고 실패 이유를 다른 메트릭으로 나눕니다. doctor 출력과 같은 대시보드에 올리면 당번이 편합니다.
curl -sS -X POST 'https://hooks.staging.example/openclaw/github' \
-H 'Content-Type: application/json' \
-H 'X-GitHub-Delivery: test-delivery-001' \
-H 'X-Hub-Signature-256: sha256=REPLACE' \
--data-binary @fixtures/push-main.json
관측 가능성과 온콜 런북
서명 검증 실패는 보통 세 갈래로 갈립니다. 첫째는 중간 프록시가 바이트열을 바꾼 경우, 둘째는 타임스탬프 창을 벗어난 경우, 셋째는 시크릿 회전 타이밍이 어긋난 경우입니다. 로그에는 전체 본문을 넣지 말고 낮은 카디널리티 라벨만 남기십시오. 예를 들어 verify_mismatch_raw, verify_mismatch_clock, verify_mismatch_secret처럼 분리하면 대시보드가 숨 쉬고 온콜이 빨라집니다. OpenClaw 바이너리 버전, nginx 설정 해시, LaunchAgent 레이블을 하나의 상관 ID에 묶어 배포 직후 30분 동안만 집중 알람을 걸면 야간 전화를 줄일 수 있습니다.
런북 첫 줄에는 최신 openclaw doctor 출력 경로와 합성 curl 명령을 항상 적어 두십시오. Redis 키 공간이 급증하면 TTL 상한을 먼저 점검하고, 메모리 한계에 닿기 전에 아카이브 정책을 문서화합니다. MacHTML에서 빌린 Mac mini로 재현했다면 동일 픽스처를 스테이징과 프로덕션에서 각각 돌려 시간대·회선 차이를 표로 남기면 보안 검토 자료로도 재사용됩니다. 장애 후 블리즈 리뷰에서는 “왜 거절했는지”뿐 아니라 “몇 초 창을 썼는지”를 함께 기록해 다음 분기에 창 조정 근거를 남기십시오.
배포 체크리스트
- 버전 고정과 doctor JSON 스냅샷
- 1000건 합성 배달로 p95 측정
- 24시간 감사 전용 모드
- 강제 모드 전환과 롤백 절차 확인
- 15분 이상 구·신 시크릿 병행
- 변경 티켓에 증적 첨부
FAQ
SPA와 같은 포트로 괜찮은가요?
분리를 권장합니다. 속도 제한과 WAF 규칙을 독립시킬 수 있습니다.
실패 시 HTTP 코드는?
401/403을 기본으로 하고 공급자 재시도 특성을 확인하십시오.
Apple Silicon Mac mini는 저소음·저전력으로 상시 게이트웨이에 적합합니다. macOS 네이티브 동작을 유지한 채 SSH로 자동 검증, 필요 시 VNC로 화면 조작도 가능한 클라우드로 MacHTML 렌탈은 단기 스파이크에 잘 맞습니다. HTML/CSS 감사와 채팅 승인을 엮는다면 지루할 정도로 견고한 웹훅 파이프라인을 먼저 고정하십시오.
밤에 대량 재전송이 와도 멱등 저장소와 초 단위 허용 창이 갖춰지면 운영자는 잠을 잘 수 있습니다. OpenClaw를 프로덕션 인프라로 취급하는 팀일수록 이 지루한 층에 투자하십시오.