myscode / laravel-any-trusted-proxies
Easily configurable any popular, custom or niche proxy providers for Laravel. Dynamic trusted proxies middleware with Cloudflare, Fastly, AWS CloudFront, Gcore, Bunny CDN, CDNvideo, Megafon and custom IP providers.
Package info
github.com/myscode/laravel-any-trusted-proxies
pkg:composer/myscode/laravel-any-trusted-proxies
Requires
- php: >=8.1
- illuminate/cache: ^10.0|^11.0|^12.0|^13.0
- illuminate/console: ^10.0|^11.0|^12.0|^13.0
- illuminate/http: ^10.0|^11.0|^12.0|^13.0
- illuminate/support: ^10.0|^11.0|^12.0|^13.0
Requires (Dev)
- guzzlehttp/guzzle: ^7.0
- mockery/mockery: ^1.6
- orchestra/testbench: ^8.0|^9.0|^10.0|^11.0
- phpunit/phpunit: ^10.0|^11.0
README
Easily configurable any popular, custom, or niche proxy providers for Laravel.
A Laravel package for dynamic loading of trusted proxy IPs from multiple CDN and proxy providers: Cloudflare, Fastly, AWS CloudFront, Gcore, Bunny CDN, CDNvideo, Megafon β and any custom provider you add.
Table of Contents
- Features
- Requirements
- Installation
- Quick Start
- Publishing Configuration
- Middleware Setup
- Configuration
- IP Address Formats
- Cache Safety
- Available Commands
- Scheduler Setup
- Architecture
- Adding a Custom Provider
- Testing
- License
Features
- Pick any providers β enable only the ones you need via a single
.envvariable - 7 built-in providers: Cloudflare, Fastly, AWS CloudFront, Gcore, Bunny CDN, CDNvideo, Megafon
- Custom provider support β add your own or niche providers via the
IpProviderinterface - HTTP retries via
Http::retrywith configurable attempts and delay - Safe cache refresh: if any provider fails, the existing cache is preserved β partial results are never saved
- Middleware that injects trusted proxy IPs at runtime β replaces the stock
TrustProxiesmiddleware - Artisan command for manual/scheduled cache refresh
- CIDR and plain IP support β transparently works with both formats
Requirements
| Dependency | Version |
|---|---|
| PHP | >= 8.1 |
| Laravel | 10.x or 11.x |
| Composer | >= 2.0 |
Installation
composer require myscode/laravel-any-trusted-proxies
The package uses Laravel auto-discovery β the ServiceProvider is registered automatically.
Quick Start
- Add to your
.envthe providers you want to enable:
TRUSTED_PROXIES=cloudflare,fastly
- Register the middleware in
bootstrap/app.php(Laravel 11+):
->withMiddleware(function (Middleware $middleware) { $middleware->replace( \Illuminate\Http\Middleware\TrustProxies::class, \Myscode\AnyTrustedProxies\Http\Middleware\TrustProxies::class ); })
- Done! The trusted proxy IPs will be fetched, cached, and applied automatically.
If TRUSTED_PROXIES is left empty, no providers are loaded β the middleware will have an empty proxy list.
Publishing Configuration
php artisan vendor:publish --tag=trusted-proxy-config
After publishing, the file will be placed at config/trusted-proxy.php. You can add custom providers, change TTL, or tweak retry settings.
Middleware Setup
The package provides its own middleware Myscode\AnyTrustedProxies\Http\Middleware\TrustProxies that replaces the stock Illuminate\Http\Middleware\TrustProxies.
Laravel 11+
->withMiddleware(function (Middleware $middleware) { $middleware->replace( \Illuminate\Http\Middleware\TrustProxies::class, \Myscode\AnyTrustedProxies\Http\Middleware\TrustProxies::class ); })
Laravel 10
In app/Http/Kernel.php:
protected $middleware = [ // ... \Myscode\AnyTrustedProxies\Http\Middleware\TrustProxies::class, ];
Configuration
Environment Variables
All configuration can be done through .env:
# Comma-separated list of providers to enable (leave empty to disable all) TRUSTED_PROXIES=cloudflare,fastly,aws_cloudfront # Cache key (optional, default: trusted_proxy_ips) TRUSTED_PROXY_CACHE_KEY=trusted_proxy_ips # Cache TTL in seconds (optional, default: 604800 = 7 days) TRUSTED_PROXY_TTL=604800 # HTTP retry attempts (optional, default: 3) TRUSTED_PROXY_RETRY_TIMES=3 # HTTP retry delay in ms (optional, default: 200) TRUSTED_PROXY_RETRY_SLEEP=200
Options Reference
| Option | Type | .env Variable |
Description | Default |
|---|---|---|---|---|
cache_key |
string |
TRUSTED_PROXY_CACHE_KEY |
Cache key for storing IPs | trusted_proxy_ips |
ttl |
int |
TRUSTED_PROXY_TTL |
Cache lifetime in seconds | 604800 (7 days) |
retry.times |
int |
TRUSTED_PROXY_RETRY_TIMES |
Number of HTTP retry attempts | 3 |
retry.sleep |
int |
TRUSTED_PROXY_RETRY_SLEEP |
Delay between retries (ms) | 200 |
enabled |
array |
TRUSTED_PROXIES |
Comma-separated provider names to enable | [] |
providers |
array |
β | Map of all available providers (name β class) | all built-in |
headers |
int |
β | Bitmask of trusted forwarded headers | HEADER_X_FORWARDED_ALL |
The headers value is a bitmask from Illuminate\Http\Request:
| Constant | Value | Description |
|---|---|---|
HEADER_X_FORWARDED_FOR |
0b00000010 |
Client IP |
HEADER_X_FORWARDED_HOST |
0b00000100 |
Host |
HEADER_X_FORWARDED_PORT |
0b00001000 |
Port |
HEADER_X_FORWARDED_PROTO |
0b00010000 |
Protocol (http/https) |
HEADER_X_FORWARDED_ALL |
0b11111110 |
All headers |
Available Providers
| Provider | .env Key |
Class | Response Type | Data Source |
|---|---|---|---|---|
| Cloudflare | cloudflare |
CloudflareIpProvider |
Plain text | cloudflare.com/ips-v4 + ips-v6 |
| Fastly | fastly |
FastlyIpProvider |
JSON | api.fastly.com/public-ip-list |
| AWS CloudFront | aws_cloudfront |
AwsCloudFrontIpProvider |
JSON | ip-ranges.amazonaws.com/ip-ranges.json |
| Gcore | gcore |
GcoreIpProvider |
JSON | api.gcore.com/cdn/public_ips_list |
| Bunny CDN | bunny |
BunnyIpProvider |
JSON | api.bunny.net/system/edgeserverlist |
| CDNvideo | cdnvideo |
CdnvideoIpProvider |
JSON | api.cdnvideo.ru/app/nodes/v2/ip2origin |
| Megafon | megafon |
MegafonIpProvider |
JSON | api.lk.cdn.megafon.ru/cdn/public_ips_list |
IP Address Formats
The package does not validate or transform IP addresses on its own β it passes them "as is" to Laravel's standard middleware. Verification happens at the framework level via Symfony's IpUtils::checkIp().
Both formats are supported:
| Format | Example | How it is checked |
|---|---|---|
| CIDR | 173.245.48.0/20 |
Subnet membership check |
| Plain IPv4 | 192.168.1.1 |
Exact match (equivalent to /32) |
| Plain IPv6 | 2400:cb00::1 |
Exact match (equivalent to /128) |
Cache Safety
- On
refresh/load, the list is cached only if all enabled providers succeed - If any provider fails, the existing cache is used (if available), so the application never loses its trusted proxies
- Partial results on failure are never saved β this prevents a scenario where a single failed provider removes its IPs from the trusted list
- All IPs are deduplicated across providers
Available Commands
any-trustedproxy:reload
Force-refreshes the trusted proxy list from all enabled providers:
php artisan any-trustedproxy:reload
Output:
Trusted proxies refreshed. Count: 42
Exit codes:
0(SUCCESS) β refresh completed successfully
Scheduler Setup
use Illuminate\Support\Facades\Schedule; Schedule::command('any-trustedproxy:reload')->weekly(); // or: ->daily(), ->twiceDaily(), ->everySixHours()
Architecture
βββββββββββββββββββββββββββββββββββββββββββββββ
β .env β
β TRUSTED_PROXIES=cloudflare,fastly β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββ
β ServiceProvider β
β βββββββββββββββββββββββββββββββββββββββββ β
β β Read enabled[] from config β β
β β Filter providers map by enabled β β
β β Instantiate only selected providers β β
β βββββββββββββββββ¬ββββββββββββββββββββββββ β
ββββββββββββββββββββΌβββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββ
β HTTP Request β
ββββββββββββββββββ¬βββββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββ
β Middleware: TrustProxies β
β βββββββββββββββββββββββββββββββββββββββββ β
β β $this->proxies = TrustedProxy::load()β β
β β $this->headers = config(...) β β
β βββββββββββββββββ¬ββββββββββββββββββββββββ β
ββββββββββββββββββββΌβββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββ
β Facade: TrustedProxy β
β βββββββββββββββββββββββββββββββββββββββββ β
β β IpCacheManager β β
β β βββββββββββββββββββββββββββββββββββ β β
β β β Cache::get(cache_key) β β β
β β β βββ hit β return cached β β β
β β β βββ miss β fetchFromProviders β β β
β β ββββββββββββββββ¬βββββββββββββββββββ β β
β βββββββββββββββββββΌββββββββββββββββββββββ β
ββββββββββββββββββββββΌβββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββ
β IpProvider[] (only enabled) β
β ββββββββββββ ββββββββββββ ββββββββββββββ β
β βCloudflareβ β Fastly β β Gcore β β
β β getIps() β β getIps() β β getIps() β β
β ββββββ¬ββββββ ββββββ¬ββββββ βββββββ¬βββββββ β
β βββββββββββββββ΄ββββββββββββββ β
β β β
β array_merge + β
β array_unique β
β βΌ β
β Cache::put() β
βββββββββββββββββββββββββββββββββββββββββββββββ
Key Components
| Component | Purpose |
|---|---|
IpProvider (interface) |
Contract for all providers: getIps(): array |
FetchesWithRetry (trait) |
HTTP requests with retries: getJsonWithRetry() and getTextLinesWithRetry() |
IpCacheManager |
Orchestration: collects IPs from providers, caching, fail-safe logic |
TrustProxies (middleware) |
Replaces stock middleware β injects proxies at runtime |
TrustedProxy (facade) |
Convenient access to IpCacheManager |
TrustedProxyServiceProvider |
Laravel registration: singleton, TRUSTED_PROXIES filtering, command, config |
ReloadProxiesCommand |
Artisan command for forced cache refresh |
Adding a Custom Provider
Implement the IpProvider interface and optionally use the FetchesWithRetry trait:
<?php namespace App\TrustedProxies; use Myscode\AnyTrustedProxies\Contracts\IpProvider; use Myscode\AnyTrustedProxies\Services\Concerns\FetchesWithRetry; class MyCdnProvider implements IpProvider { use FetchesWithRetry; public function getIps(): array { // Option 1: JSON API $data = $this->getJsonWithRetry('https://api.mycdn.com/public-ips'); return collect($data['ip_ranges'] ?? []) ->pluck('subnet') ->filter() ->values() ->all(); // Option 2: Plain text (one IP per line) // return $this->getTextLinesWithRetry('https://mycdn.com/ips.txt'); // Option 3: Static list // return ['10.0.0.0/8', '172.16.0.0/12']; } }
Register it in config/trusted-proxy.php and .env:
// config/trusted-proxy.php 'providers' => [ // ...built-in providers... 'my_cdn' => \App\TrustedProxies\MyCdnProvider::class, ],
# .env
TRUSTED_PROXIES=cloudflare,fastly,my_cdn
Implementation Guidelines
getIps()must return a flat array of strings β CIDR (10.0.0.0/8) or plain IP (192.168.1.1)- Do not throw exceptions β
IpCacheManagercatches\Throwableand logs the error without breaking other providers - Use the
FetchesWithRetrytrait for automatic retries according to your retry settings - Filter out empty values β use
array_filteron the result
Testing
composer install composer test composer test-coverage # with coverage
Tests use Orchestra Testbench. HTTP requests are mocked via Http::fake().
License
MIT License β see LICENSE.