feat: trust X-Remote-User only from the proxy (HADO_TRUSTED_PROXIES); open tailnet inbound for the agent

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BCrwHHnGCB5XH968Nxokqw
This commit is contained in:
nikita.hohlov
2026-09-05 07:25:31 -03:00
parent 36d6af659e
commit bc82bbab19
5 changed files with 40 additions and 4 deletions

View File

@@ -5,11 +5,14 @@ namespace App\Http\Middleware;
use App\Ingest\EventUpserter;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\IpUtils;
use Symfony\Component\HttpFoundation\Response;
/**
* Доверяет X-Remote-User от Caddy forward_auth (сеть изолирована, как в sekai).
* На публичных маршрутах (/api, /a, /hooks) этот middleware не стоит.
* Доверяет X-Remote-User от Caddy forward_auth и только ему: заголовок принимается,
* если TCP-сосед (REMOTE_ADDR, не X-Forwarded-For) из HADO_TRUSTED_PROXIES. Порт hado
* виден и из тейлнета (агент), оттуда подделать SSO-заголовок нельзя.
* На публичных маршрутах (/api, /a, /hooks, /mcp) этот middleware не стоит.
*/
class RemoteUser
{
@@ -18,6 +21,9 @@ class RemoteUser
public function handle(Request $request, Closure $next): Response
{
$login = trim((string) $request->header('X-Remote-User', ''));
if ($login !== '' && ! IpUtils::checkIp((string) $request->server('REMOTE_ADDR'), config('hado.trusted_proxies'))) {
return response()->json(['message' => 'X-Remote-User принимается только от прокси'], 401);
}
if ($login === '' && app()->environment('local')) {
// Dev без хаба: HADO_DEV_USER подставляет пользователя. В проде не работает.
$login = trim((string) config('hado.dev_user'));