RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝 #1
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/rpi4-dual-module-unified-server"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝
1. 배경 / 목적
서버실 모니터링을 하나의 시스템으로 통합한다. Raspberry Pi 4 센서 모듈 2개가 각각
cafe24 서버로 데이터를 전송하고, 서버가 저장·임계판정·SMS·단일 대시보드 표시를 담당한다.
raspberry_pi4/,sensor_id=1)raspberry_pi4_sht30/,sensor_id=2)기존에는 온습도(이 repo의
php/서버)와 누수(레거시 누수 서버)가 분리되어 있었고서명 방식도 달랐다. 본 PR로 두 모듈을 동일 서버·동일 서명(X-Signature HMAC)으로 통합하여
대시보드 한 화면에서 온습도 + 누수 상태 + 현장 사진을 함께 본다.
2. 2번 모듈 신규 —
raspberry_pi4_sht30/(온습도)STM32 펌웨어
sht30_fw동작을 Raspberry Pi 4 + Python으로 이식.sht30_sensor.pystartup→periodic, SIGTERM 정상종료sht30_driver.pywire.pyjsonbody.c/sig.c와 바이트 동일)config.py/config_local.example.pyinstall.sh/vendor.shtest_sensor.py/test_connection.pysystemd/sht30-sensor.service0x44, 4.7kΩ 풀업temp=-45+175·raw_t/65535,rh=100·raw_rh/65535, CRC-8(poly 0x31, init 0xFF)device_id, device_location, sensor_id, sensor_name, event_type, timestamp, metric_type="sht30", temperature_c, humidity_percent, metric_status, app_version3. 1번 모듈 통합 —
raspberry_pi4/(누수+카메라)sha256(API_KEY + 정렬 JSON)body-field 서명 → raw-bodyX-SignatureHMAC(2번 모듈과 동일 스킴). 본문을 고정 순서 문자열로 만들어 그 바이트에서명하고 그대로 POST(
data=body_bytes).{device_id, device_location, sensor_id, sensor_name, event_type, is_leak, timestamp}device_id|sensor_id|log_id|timestamp(공백 없음),X-Signature헤더. 서버photo_upload.php재구성 canonical과 바이트 동일.config_local.example.py:API_URL/PHOTO_UPLOAD_URL을 통합 서버로,API_KEY는 서버와 동일.4. 서버 통합 (
php/)api/sensor_data.phpleak_alert/leak_recovery수신,is_leak처리,leak_incident개시/종료,leak_alert응답에log_id반환. SHT30 측정 경로 100% 유지api/photo_upload.php(신규)finfoMIME·크기상한·서버생성 무작위 파일명·nonce 멱등·log_id↔sensor_id결속photo.php(신규)realpath봉쇄(경로순회 방어),readfileimage/jpegdashboard.phpleak_incident이력 +photo.php?id=썸네일), 이벤트 라벨누수감지/누수복구, 제목 "온습도·누수 통합"sms_send.phpsend_leak_alert_sms(쿨다운) /send_leak_recovery_sms(경보 후에만)config.php[누수감지]/[누수복구]태그, 쿨다운 상수, SMS 요약에 누수 카운트var/.htaccess,var/photos/.htaccess(신규)Require all denied+ PHP 실행차단DB
sql/migration_add_leak.sql(신규, 가산·멱등) — 기존 온습도 서버에 누수 복원(
sensor_log.is_leak/sensor_status.is_leak,event_typeENUM에 leak 값,leak_incident+leak_photo테이블).sensor_metric(SHT30) 보존. 재실행 안전.sql/schema_sht30.sql— 신규(통합) 설치용. 누수 요소 포함.5. 보안 하드닝 (외부 펜테스트 대비)
2중 독립 리뷰 → 확정 CRITICAL/HIGH = 0.
(TOTP 재생·CRON_SECRET 유추·setup_mfa 재등록 등 — 비번/키 선보유 필요거나 시크릿 미영속화)
var/노출 전부 방어 확인.적용한 하드닝(저위험, 무회귀):
cron_heartbeat.php—api_key_is_default()fail-closed (신규설치 예측가능 CRON_SECRET 무력화)setup_mfa.php— MFA 설정완료 후 부트스트랩 토큰 경로 차단var/·var/photos/— PHP 실행차단(engine off+ FilesMatch + RemoveHandler) → 업로드→RCE 폴리글랏 봉쇄php/.htaccess— HSTS 헤더 추가미반영(문서화): CSP
unsafe-inline제거는 대시보드 인라인 스크립트/스타일 nonce 리팩터필요 → 회귀위험으로 별도단계. (현 XSS 실위험 없음 — 출력 전부
htmlspecialchars)6. 검증 내역
wire.py(2번)·leak_sensor.py(1번) 모두 본문/서명이 펌웨어reference.py및 독립 HMAC과 바이트 일치(한글 UTF-8,"/\이스케이프, round-half-up,max uint32 ts 엣지케이스 포함). 사진 canonical 클라↔서버 동일.
py_compile+ import 그래프 + 자가점검(CRC0xBEEF→0x92등) 통과.7. 배포 절차
각 라즈베리파이4 (모듈당 1대 또는 한 대에 둘 다 — 핀 충돌 없음)
cp config_local.example.py config_local.py→API_URL/API_KEY/DEVICE_ID(+1번PHOTO_UPLOAD_URL)./install.sh→ systemd enablecafe24 서버 (1회)
sql/migration_add_leak.sql; 신규 →sql/schema_sht30.sqlphp/업로드 (신규photo.php,api/photo_upload.php,var/.htaccess포함)php/var/photos/웹서버 쓰기권한config.local.php의API_KEY= 라즈베리파이와 동일8. 배포 전 체크리스트
php -l php/cron_heartbeat.php php/setup_mfa.php php/dashboard.php php/photo.php php/api/photo_upload.php/
php tests/security_hardening_test.php(작업 환경엔 PHP 없어 미실행)migration_add_leak.sql1회 적용php/var/photos/쓰기권한API_KEY실값 설정 + MFA 등록 후MFA_SETUP_TOKEN비우기9. 주의 / 리스크
순수 이 작업분만 보려면 핵심 경로는
raspberry_pi4*/,php/api/,php/photo.php,sql/migration_add_leak.sql,SYSTEM_OVERVIEW.md.php -l게이트 필수.requests/smbus2등 의존성은vendor.sh로 사전 번들(aarch64).