├── .github ├── ISSUE_TEMPLATE │ └── laravel-9-updates.md └── workflows │ └── tests.yml ├── LICENSE.md ├── composer.json ├── config └── trustedproxy.php └── src ├── TrustProxies.php └── TrustedProxyServiceProvider.php /.github/ISSUE_TEMPLATE/laravel-9-updates.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Laravel 9 Updates 3 | about: Inform about Laravel 9 changes 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 15 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Tests 4 | 5 | # Controls when the action will run. 6 | on: 7 | push: 8 | pull_request: 9 | 10 | # Allows you to run this workflow manually from the Actions tab 11 | workflow_dispatch: 12 | 13 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 14 | jobs: 15 | # This workflow contains a single job called "build" 16 | run_tests: 17 | # The type of runner that the job will run on 18 | runs-on: ubuntu-latest 19 | 20 | strategy: 21 | fail-fast: true 22 | matrix: 23 | php: [7.2, 7.3, 7.4, 8.0, 8.1] 24 | 25 | name: PHP ${{ matrix.php }} 26 | 27 | # Steps represent a sequence of tasks that will be executed as part of the job 28 | steps: 29 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 30 | - uses: actions/checkout@v2 31 | 32 | - name: Checkout code 33 | uses: actions/checkout@v2 34 | 35 | - name: Setup PHP 36 | uses: shivammathur/setup-php@v2 37 | with: 38 | php-version: ${{ matrix.php }} 39 | extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite 40 | tools: composer:v2 41 | coverage: none 42 | 43 | - name: Install dependencies 44 | uses: nick-invision/retry@v1 45 | with: 46 | timeout_minutes: 5 47 | max_attempts: 5 48 | command: composer update --prefer-dist --no-interaction --no-progress 49 | 50 | - name: Execute tests 51 | run: vendor/bin/phpunit --verbose 52 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 12 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 13 | THE SOFTWARE. 14 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fideloper/proxy", 3 | "description": "Set trusted proxies for Laravel", 4 | "keywords": ["proxy", "trusted proxy", "load balancing"], 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Chris Fidao", 9 | "email": "fideloper@gmail.com" 10 | } 11 | ], 12 | "require": { 13 | "php": ">=5.4.0", 14 | "illuminate/contracts": "^5.0|^6.0|^7.0|^8.0|^9.0" 15 | }, 16 | "require-dev": { 17 | "illuminate/http": "^5.0|^6.0|^7.0|^8.0|^9.0", 18 | "mockery/mockery": "^1.0", 19 | "phpunit/phpunit": "^8.5.8|^9.3.3" 20 | }, 21 | "autoload": { 22 | "psr-4": { 23 | "Fideloper\\Proxy\\": "src/" 24 | } 25 | }, 26 | "extra": { 27 | "laravel": { 28 | "providers": [ 29 | "Fideloper\\Proxy\\TrustedProxyServiceProvider" 30 | ] 31 | } 32 | }, 33 | "minimum-stability": "dev", 34 | "prefer-stable": true 35 | } 36 | -------------------------------------------------------------------------------- /config/trustedproxy.php: -------------------------------------------------------------------------------- 1 | null, // [,], '*', ',' 19 | 20 | /* 21 | * To trust one or more specific proxies that connect 22 | * directly to your server, use an array or a string separated by comma of IP addresses: 23 | */ 24 | // 'proxies' => ['192.168.1.1'], 25 | // 'proxies' => '192.168.1.1, 192.168.1.2', 26 | 27 | /* 28 | * Or, to trust all proxies that connect 29 | * directly to your server, use a "*" 30 | */ 31 | // 'proxies' => '*', 32 | 33 | /* 34 | * Which headers to use to detect proxy related data (For, Host, Proto, Port) 35 | * 36 | * Options include: 37 | * 38 | * - All headers (see below) - Trust all x-forwarded-* headers 39 | * - Illuminate\Http\Request::HEADER_FORWARDED - Use the FORWARDED header to establish trust 40 | * - Illuminate\Http\Request::HEADER_X_FORWARDED_AWS_ELB - If you are using AWS Elastic Load Balancer 41 | * 42 | * @link https://symfony.com/doc/current/deployment/proxies.html 43 | */ 44 | 'headers' => Illuminate\Http\Request::HEADER_X_FORWARDED_FOR | Illuminate\Http\Request::HEADER_X_FORWARDED_HOST | Illuminate\Http\Request::HEADER_X_FORWARDED_PORT | Illuminate\Http\Request::HEADER_X_FORWARDED_PROTO | Illuminate\Http\Request::HEADER_X_FORWARDED_AWS_ELB, 45 | 46 | ]; 47 | -------------------------------------------------------------------------------- /src/TrustProxies.php: -------------------------------------------------------------------------------- 1 | config = $config; 40 | } 41 | 42 | /** 43 | * Handle an incoming request. 44 | * 45 | * @param \Illuminate\Http\Request $request 46 | * @param \Closure $next 47 | * 48 | * @throws \Symfony\Component\HttpKernel\Exception\HttpException 49 | * 50 | * @return mixed 51 | */ 52 | public function handle(Request $request, Closure $next) 53 | { 54 | $request::setTrustedProxies([], $this->getTrustedHeaderNames()); // Reset trusted proxies between requests 55 | $this->setTrustedProxyIpAddresses($request); 56 | 57 | return $next($request); 58 | } 59 | 60 | /** 61 | * Sets the trusted proxies on the request to the value of trustedproxy.proxies 62 | * 63 | * @param \Illuminate\Http\Request $request 64 | */ 65 | protected function setTrustedProxyIpAddresses(Request $request) 66 | { 67 | $trustedIps = $this->proxies ?: $this->config->get('trustedproxy.proxies'); 68 | 69 | // Trust any IP address that calls us 70 | // `**` for backwards compatibility, but is deprecated 71 | if ($trustedIps === '*' || $trustedIps === '**') { 72 | return $this->setTrustedProxyIpAddressesToTheCallingIp($request); 73 | } 74 | 75 | // Support IPs addresses separated by comma 76 | $trustedIps = is_string($trustedIps) ? array_map('trim', explode(',', $trustedIps)) : $trustedIps; 77 | 78 | // Only trust specific IP addresses 79 | if (is_array($trustedIps)) { 80 | return $this->setTrustedProxyIpAddressesToSpecificIps($request, $trustedIps); 81 | } 82 | } 83 | 84 | /** 85 | * Specify the IP addresses to trust explicitly. 86 | * 87 | * @param \Illuminate\Http\Request $request 88 | * @param array $trustedIps 89 | */ 90 | private function setTrustedProxyIpAddressesToSpecificIps(Request $request, $trustedIps) 91 | { 92 | $request->setTrustedProxies((array) $trustedIps, $this->getTrustedHeaderNames()); 93 | } 94 | 95 | /** 96 | * Set the trusted proxy to be the IP address calling this servers 97 | * 98 | * @param \Illuminate\Http\Request $request 99 | */ 100 | private function setTrustedProxyIpAddressesToTheCallingIp(Request $request) 101 | { 102 | $request->setTrustedProxies([$request->server->get('REMOTE_ADDR')], $this->getTrustedHeaderNames()); 103 | } 104 | 105 | /** 106 | * Retrieve trusted header name(s), falling back to defaults if config not set. 107 | * 108 | * @return int A bit field of Request::HEADER_*, to set which headers to trust from your proxies. 109 | */ 110 | protected function getTrustedHeaderNames() 111 | { 112 | $headers = $this->headers ?: $this->config->get('trustedproxy.headers'); 113 | switch ($headers) { 114 | case 'HEADER_X_FORWARDED_AWS_ELB': 115 | case Request::HEADER_X_FORWARDED_AWS_ELB: 116 | return Request::HEADER_X_FORWARDED_AWS_ELB; 117 | break; 118 | case 'HEADER_FORWARDED': 119 | case Request::HEADER_FORWARDED: 120 | return Request::HEADER_FORWARDED; 121 | break; 122 | case 'HEADER_X_FORWARDED_FOR': 123 | case Request::HEADER_X_FORWARDED_FOR: 124 | return Request::HEADER_X_FORWARDED_FOR; 125 | break; 126 | case 'HEADER_X_FORWARDED_HOST': 127 | case Request::HEADER_X_FORWARDED_HOST: 128 | return Request::HEADER_X_FORWARDED_HOST; 129 | break; 130 | case 'HEADER_X_FORWARDED_PORT': 131 | case Request::HEADER_X_FORWARDED_PORT: 132 | return Request::HEADER_X_FORWARDED_PORT; 133 | break; 134 | case 'HEADER_X_FORWARDED_PROTO': 135 | case Request::HEADER_X_FORWARDED_PROTO: 136 | return Request::HEADER_X_FORWARDED_PROTO; 137 | break; 138 | default: 139 | return Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_AWS_ELB; 140 | } 141 | 142 | return $headers; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/TrustedProxyServiceProvider.php: -------------------------------------------------------------------------------- 1 | app instanceof LaravelApplication && $this->app->runningInConsole()) { 21 | $this->publishes([$source => config_path('trustedproxy.php')]); 22 | } elseif ($this->app instanceof LumenApplication) { 23 | $this->app->configure('trustedproxy'); 24 | } 25 | 26 | 27 | if ($this->app instanceof LaravelApplication && ! $this->app->configurationIsCached()) { 28 | $this->mergeConfigFrom($source, 'trustedproxy'); 29 | } 30 | } 31 | 32 | /** 33 | * Register the service provider. 34 | * 35 | * @return void 36 | */ 37 | public function register() 38 | { 39 | // 40 | } 41 | } 42 | --------------------------------------------------------------------------------