From 892e37e72de6f1aeefabb4ab076dfebf08902351 Mon Sep 17 00:00:00 2001 From: seo Date: Tue, 28 Jul 2026 22:36:04 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BB=A8=ED=8A=B8=EB=A1=A4=20mnt=20=EA=B3=B5?= =?UTF-8?q?=EC=9A=A9=20=EC=9D=B8=EC=A6=9D=20=EC=9D=98=EC=A1=B4=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +-- config/config.php | 75 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 53 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 006ab0b..f4c31e3 100644 --- a/README.md +++ b/README.md @@ -273,5 +273,5 @@ control-wifi-observe.service - Reboot API 사용 전 웹 서버 실행 계정의 sudoers에 `/usr/sbin/reboot` 비밀번호 없는 실행 권한이 제한적으로 설정되어 있는지 확인합니다. - 저전압/스로틀링이 `N/A`로 보이면 웹 서버 실행 계정의 `/dev/vcio` 접근 권한과 `/usr/bin/vcgencmd get_throttled` sudoers 허용 여부를 확인합니다. - 언어/테마 표시가 예상과 다르면 브라우저 localStorage의 `controlLang`, `controlTheme` 값을 확인합니다. -- `/mnt/synology-web`는 원격 Synology NFS 마운트이며 `sec=sys` 숫자 UID/GID 매핑을 사용합니다. 로컬 `seo`의 기본 UID/GID만으로는 `/mnt/synology-web/log`, `/mnt/synology-web/report`, `/mnt/synology-web/config`에 쓸 수 없고, `synologyweb` primary group으로 실행해야 합니다. `/home/seo/log.sh`는 시작 시 `sg synologyweb`으로 재실행하도록 구성합니다. -- `/mnt/synology-docker/homeassistant/config`는 현재 일반 `seo`와 `synologyweb` primary group 모두 쓰기 가능합니다. +- 시놀로지 운영 상태 확인은 NFS 경로가 아니라 SSH와 HTTPS API를 기준으로 합니다. Control 런타임에서 필요한 공용 HA 설정은 `/home/seo/secret/control.php`의 `common` 항목에 둡니다. +- smartban 판단 로그는 로컬 `logger -t smartban`으로 남기고 rsyslog/TLS가 시놀로지 Log Center로 전달합니다. diff --git a/config/config.php b/config/config.php index 65ed608..cbfaec1 100644 --- a/config/config.php +++ b/config/config.php @@ -865,36 +865,66 @@ function control_admin_session_from_rhymix_or_custom(): bool } $checked = false; - $commonAuth = '/mnt/synology-web/custom/common/auth.php'; - if (!is_file($commonAuth) || !is_readable($commonAuth)) { + $cookieHeader = trim((string)($_SERVER['HTTP_COOKIE'] ?? '')); + if ($cookieHeader === '') { return false; } - try { - require_once $commonAuth; - $checked = (function_exists('custom_auth_cookie_is_admin') && custom_auth_cookie_is_admin()) - || (function_exists('custom_is_site_admin') && custom_is_site_admin()); - } catch (Throwable) { - $checked = false; - } + $session = control_launcher_session($cookieHeader); + $checked = is_array($session) && !empty($session['authenticated']) && !empty($session['admin']); return $checked; } function clear_common_admin_auth_cookie_if_available(): void { - $commonAuth = '/mnt/synology-web/custom/common/auth.php'; - if (!is_file($commonAuth) || !is_readable($commonAuth)) { - return; + $secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'); + foreach (['custom_access', 'access'] as $name) { + setcookie($name, '', [ + 'expires' => time() - 3600, + 'path' => '/', + 'secure' => $secure, + 'httponly' => $name !== 'access', + 'samesite' => 'Strict', + ]); + } +} + +function control_launcher_session(string $cookieHeader): ?array +{ + $url = 'https://chaegeon.com/custom/launcher/api.php?session=1'; + $body = false; + + if (function_exists('curl_init')) { + $ch = curl_init($url); + if ($ch !== false) { + curl_setopt_array($ch, [ + CURLOPT_RETURNTRANSFER => true, + CURLOPT_CONNECTTIMEOUT => 2, + CURLOPT_TIMEOUT => 4, + CURLOPT_HTTPHEADER => [ + 'Cookie: ' . $cookieHeader, + 'User-Agent: control-auth/1.0', + ], + ]); + $body = curl_exec($ch); + curl_close($ch); + } } - try { - require_once $commonAuth; - if (function_exists('custom_clear_auth_cookie')) { - custom_clear_auth_cookie(); - } - } catch (Throwable) { + if ($body === false) { + $context = stream_context_create([ + 'http' => [ + 'method' => 'GET', + 'timeout' => 4, + 'header' => "Cookie: {$cookieHeader}\r\nUser-Agent: control-auth/1.0\r\n", + ], + ]); + $body = @file_get_contents($url, false, $context); } + + $data = is_string($body) ? json_decode($body, true) : null; + return is_array($data) ? $data : null; } function require_login(): void @@ -1256,17 +1286,14 @@ function update_presence_fan_policy_state(array $values): void function control_common_config(): array { + global $controlSecretConfig; + static $config = null; if ($config !== null) { return $config; } - $file = '/mnt/synology-web/custom/common/config.php'; - if (!is_file($file)) { - return $config = []; - } - - $loaded = require $file; + $loaded = $controlSecretConfig['common'] ?? []; return $config = is_array($loaded) ? $loaded : []; }