Sign inSign up

3735943886/zigbang-relay

By 3735943886

Updated 21 days ago

직방 도어락 로컬 릴레이 서버

Image
Networking
Security
0

1.9K

3735943886/zigbang-relay repository overview

relay 배포 (Docker)

relay는 직방(삼성SDS) 도어락과 실클라우드 사이를 중계하는 상시 데몬이다(투명 MQTTS+UDP 프록시 — 락은 그대로 두고 전체 트래픽을 관찰하거나, 필요하면 대신 응답한다).

0. 디렉터리 레이아웃 — 호스트에 폴더 하나, 컨테이너엔 /data 하나로 마운트

/opt/zigbang-relay/(경로는 아무 데나 상관없음) 하나에 아래 파일들을 넣고, 이 디렉터리 전체를 컨테이너의 /data에 통째로 마운트한다(볼륨을 여러 개로 쪼개지 않는 이유는 relay의 설정 파일 안 모든 경로가 이 디렉터리 기준 상대경로라서, 디렉터리 하나만 옮기면 그대로 재현되기 때문):

경로무엇인가어떻게 생기나
relay.toml설정 파일docker/relay.toml.example 편집
rules/*.rhai메시지 응답 규칙docker/rules/ 그대로 복사
certs/fullchain.pem, certs/privkey.pemTLS 인증서2단계에서 발급
state/replay.json재생 캐시(장애 대응용)자동 생성, 미리 안 만들어도 됨
logs/relay 로그자동 생성

1. relay.toml 작성

relay.toml을 아래 내용으로 만들고, 표시된 값들을 실제 값으로 바꾼다:

# 게이트웨이 배포용 relay config (상대경로). 전부 이 파일과 같은 디렉터리(/opt/zigbang-relay 등,
# systemd WorkingDirectory / docker WORKDIR) 기준 — 그 디렉터리 하나만 통째로 배포/마운트하면 됨
# (README.md 참조). 실제 값(도메인/포트)은 설치 후 이 파일에서 편집.
# 규칙: rules/*.rhai(mtime 핫리로드 — 수정시 재시작 불필요). 설계: DESIGN.md(레포 밖 private).

log_level = "info"                 # error|warn|info|debug|trace
observer = "0.0.0.0:9883"          # 평문 MQTT 관찰/명령(로컬신뢰망 전용 — 방화벽으로 막을 것)
# observer_user = "watcher"        # 둘 다 설정해야 인증 활성화(CONNECT username/password 검사).
# observer_pass = "바꿀것"          # 주석 처리(기본)면 예전처럼 무인증 — 방화벽만으로 막는 셈.
rules_file = "rules"
replay_store = "state/replay.json"
log_dir = "logs"

# TLS: certbot deploy-hook 가 이 디렉터리의 certs/ 로 cert 를 복사해준다(README 참조).
cert_file = "certs/fullchain.pem"
cert_key  = "certs/privkey.pem"
cert_name = "relay.example.com"    # ← 실제 주입 도메인으로 변경
upstream_insecure = true           # 실클라우드로 나갈 때 그쪽 cert 검증 안 함(기술부채, 낮은 우선순위)

answered_ttl_secs = 120
answered_cap = 8192
reconnect_secs = 15

[[route]]
name = "mqtts"
proto = "mqtts"
mode = "proxy"                     # proxy(순수 통과+관찰, 안전한 기본값) | shadow | decloud
listen = "0.0.0.0:18883"
upstream = "mqtttcp.homeiot.zigbang-iot.com:8883"

[[route]]
name = "holepunch"
proto = "udp"
mode = "proxy"
listen = "0.0.0.0:5683"
upstream = "mqttudp.homeiot.zigbang-iot.com:5683"

listen 포트(18883/5683)는 도어락이 실제로 접속해오는 주소다 — 도어락 등록(provisioning) 때 주입한 serviceUrl/포트가 이 컨테이너를 가리켜야 한다. upstream은 진짜 직방 클라우드 브로커 주소(프로토콜 리버싱으로 확인된 값을 씀). mode는 처음엔 proxy(순수 통과+관찰, 락 동작에 영향 없음)로 시작하는 걸 권장 — shadow/decloud는 더 적극적인 모드다.

2. rules 배치

레포의 rules을 그대로 복사한다: 이 디렉터리에 "락이 어떤 메시지를 보내면 어떻게 응답할지"를 선언하는 규칙 목록이다 — relay 바이너리 자체엔 이런 프로토콜별 로직이 없고 전부 이 파일 소관이라, 파일만 바꿔치기하면 재시작 없이동작이 바뀐다.

3. TLS 인증서 발급 (Let's Encrypt)

도어락은 공인 CA가 발급한 인증서만 수락한다(자체서명은 무조건 거부, 호스트명도 검사함 — 발급받은 도메인과 relay.tomlcert_name/provision 때 주입한 도메인이 일치해야 함). 그 도메인이 이 컨테이너가 뜬 호스트를 실제로 가리켜야 한다(A레코드로 호스트 IP 직접 지정 권장 — Cloudflare 같은 프록시형 CNAME은 HTTP-01 발급 자체가 막힐 수 있음).

sudo certbot certonly --standalone -d relay.example.com   # 최초 발급(도메인 실제 값으로)
sudo install -m 0644 /etc/letsencrypt/live/relay.example.com/fullchain.pem /opt/zigbang-relay/certs/
sudo install -m 0640 /etc/letsencrypt/live/relay.example.com/privkey.pem   /opt/zigbang-relay/certs/

자동 갱신/etc/letsencrypt/renewal-hooks/deploy/zigbang-relay.sh:

#!/usr/bin/env bash
set -e
D=relay.example.com   # ← 실제 도메인
if [[ "$RENEWED_LINEAGE" == *"/$D" ]]; then
  install -m 0644 "$RENEWED_LINEAGE/fullchain.pem" /opt/zigbang-relay/certs/fullchain.pem
  install -m 0640 "$RENEWED_LINEAGE/privkey.pem"   /opt/zigbang-relay/certs/privkey.pem
fi

chmod +x 해두면 certbot이 갱신할 때마다 자동 실행된다. relay는 cert 파일의 mtime을 감시해서 컨테이너 재시작 없이 새 인증서를 바로 반영하므로, 이 훅에 docker restart를 넣을 필요조차 없다.

4. 이미지 — Docker Hub 에서 pull

docker pull 3735943886/zigbang-relay:stable   # 항상 최신 정식버전(권장)
# 또는 특정 버전 고정: docker pull 3735943886/zigbang-relay:0.1.0

:latest도 있지만(현재는 :stable과 동일 대상) 워크플로 주석상 프리릴리스(vX.Y.Z-rc.1 등) 태그는 stable/latest를 안 건드리도록 짜여있으니, 뭘 쓸지 헷갈리면 :stable을 쓸 것.

5. 실행

docker run -d --restart=always --name zigbang-relay \
  --user $(id -u):$(id -g) \
  -p 18883:18883 -p 5683:5683/udp -p 9883:9883 \
  -v /opt/zigbang-relay:/data \
  3735943886/zigbang-relay:stable

WORKDIR /data + CMD ["relay.toml"]가 이미지에 박혀있어 인자 없이 그대로 /data/relay.toml 을 읽는다. --user $(id -u):$(id -g)로 호스트에서 /opt/zigbang-relay를 소유한 유저 그대로 넘기면 이미지 기본값(10001)과 무관하게 쓰기(state/log)가 바로 됨 — 별도 chown 불필요. -p 9883(평문 관찰자 포트)은 로컬신뢰망에서만 접근 가능하게 방화벽으로 반드시 막을 것.

6. 확인 / 관측

docker logs -f zigbang-relay
# 평문 tap (로컬신뢰망 전용, 방화벽으로 외부 차단 필수):
mosquitto_sub -h <게이트웨이> -p 9883 -t '#' -v

Tag summary

Content type

Image

Digest

sha256:1b85657e4

Size

3.2 MB

Last updated

21 days ago

docker pull 3735943886/zigbang-relay