mirror of
https://github.com/flarum/framework.git
synced 2024-11-26 10:14:16 +08:00
Fixes wrong IP address when using a reverse proxy (#2236)
Added reverse proxy support to preserve forwarded IPs
This commit is contained in:
parent
89a2a9786e
commit
a6cb962f97
|
@ -25,6 +25,7 @@ use Flarum\Http\RouteHandlerFactory;
|
||||||
use Flarum\Http\UrlGenerator;
|
use Flarum\Http\UrlGenerator;
|
||||||
use Flarum\Locale\LocaleManager;
|
use Flarum\Locale\LocaleManager;
|
||||||
use Flarum\Settings\Event\Saved;
|
use Flarum\Settings\Event\Saved;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
use Laminas\Stratigility\MiddlewarePipe;
|
use Laminas\Stratigility\MiddlewarePipe;
|
||||||
|
|
||||||
class AdminServiceProvider extends AbstractServiceProvider
|
class AdminServiceProvider extends AbstractServiceProvider
|
||||||
|
@ -48,6 +49,7 @@ class AdminServiceProvider extends AbstractServiceProvider
|
||||||
$this->app->singleton('flarum.admin.middleware', function () {
|
$this->app->singleton('flarum.admin.middleware', function () {
|
||||||
return [
|
return [
|
||||||
'flarum.admin.error_handler',
|
'flarum.admin.error_handler',
|
||||||
|
'flarum.admin.proxy_middleware',
|
||||||
HttpMiddleware\ParseJsonBody::class,
|
HttpMiddleware\ParseJsonBody::class,
|
||||||
HttpMiddleware\StartSession::class,
|
HttpMiddleware\StartSession::class,
|
||||||
HttpMiddleware\RememberFromCookie::class,
|
HttpMiddleware\RememberFromCookie::class,
|
||||||
|
@ -66,6 +68,15 @@ class AdminServiceProvider extends AbstractServiceProvider
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$this->app->bind('flarum.admin.proxy_middleware', function () {
|
||||||
|
$config = $this->app->make('flarum.config');
|
||||||
|
|
||||||
|
return new HttpMiddleware\ProxyAddress(
|
||||||
|
Arr::get($config, 'reverse_proxy.enabled', false),
|
||||||
|
Arr::get($config, 'reverse_proxy.allowed', ['127.0.0.1'])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
$this->app->singleton('flarum.admin.handler', function () {
|
$this->app->singleton('flarum.admin.handler', function () {
|
||||||
$pipe = new MiddlewarePipe;
|
$pipe = new MiddlewarePipe;
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ use Flarum\Http\Middleware as HttpMiddleware;
|
||||||
use Flarum\Http\RouteCollection;
|
use Flarum\Http\RouteCollection;
|
||||||
use Flarum\Http\RouteHandlerFactory;
|
use Flarum\Http\RouteHandlerFactory;
|
||||||
use Flarum\Http\UrlGenerator;
|
use Flarum\Http\UrlGenerator;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
use Laminas\Stratigility\MiddlewarePipe;
|
use Laminas\Stratigility\MiddlewarePipe;
|
||||||
|
|
||||||
class ApiServiceProvider extends AbstractServiceProvider
|
class ApiServiceProvider extends AbstractServiceProvider
|
||||||
|
@ -45,6 +46,7 @@ class ApiServiceProvider extends AbstractServiceProvider
|
||||||
$this->app->singleton('flarum.api.middleware', function () {
|
$this->app->singleton('flarum.api.middleware', function () {
|
||||||
return [
|
return [
|
||||||
'flarum.api.error_handler',
|
'flarum.api.error_handler',
|
||||||
|
'flarum.api.proxy_middleware',
|
||||||
HttpMiddleware\ParseJsonBody::class,
|
HttpMiddleware\ParseJsonBody::class,
|
||||||
Middleware\FakeHttpMethods::class,
|
Middleware\FakeHttpMethods::class,
|
||||||
HttpMiddleware\StartSession::class,
|
HttpMiddleware\StartSession::class,
|
||||||
|
@ -64,6 +66,15 @@ class ApiServiceProvider extends AbstractServiceProvider
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$this->app->bind('flarum.api.proxy_middleware', function () {
|
||||||
|
$config = $this->app->make('flarum.config');
|
||||||
|
|
||||||
|
return new HttpMiddleware\ProxyAddress(
|
||||||
|
Arr::get($config, 'reverse_proxy.enabled', false),
|
||||||
|
Arr::get($config, 'reverse_proxy.allowed', ['127.0.0.1'])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
$this->app->singleton('flarum.api.handler', function () {
|
$this->app->singleton('flarum.api.handler', function () {
|
||||||
$pipe = new MiddlewarePipe;
|
$pipe = new MiddlewarePipe;
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ class CreateDiscussionController extends AbstractCreateController
|
||||||
protected function data(ServerRequestInterface $request, Document $document)
|
protected function data(ServerRequestInterface $request, Document $document)
|
||||||
{
|
{
|
||||||
$actor = $request->getAttribute('actor');
|
$actor = $request->getAttribute('actor');
|
||||||
$ipAddress = Arr::get($request->getServerParams(), 'REMOTE_ADDR', '127.0.0.1');
|
$ipAddress = $request->getAttribute('ipAddress');
|
||||||
|
|
||||||
if (! $request->getAttribute('bypassFloodgate')) {
|
if (! $request->getAttribute('bypassFloodgate')) {
|
||||||
$this->floodgate->assertNotFlooding($actor);
|
$this->floodgate->assertNotFlooding($actor);
|
||||||
|
|
|
@ -63,7 +63,7 @@ class CreatePostController extends AbstractCreateController
|
||||||
$actor = $request->getAttribute('actor');
|
$actor = $request->getAttribute('actor');
|
||||||
$data = Arr::get($request->getParsedBody(), 'data', []);
|
$data = Arr::get($request->getParsedBody(), 'data', []);
|
||||||
$discussionId = Arr::get($data, 'relationships.discussion.data.id');
|
$discussionId = Arr::get($data, 'relationships.discussion.data.id');
|
||||||
$ipAddress = Arr::get($request->getServerParams(), 'REMOTE_ADDR', '127.0.0.1');
|
$ipAddress = $request->getAttribute('ipAddress');
|
||||||
|
|
||||||
if (! $request->getAttribute('bypassFloodgate')) {
|
if (! $request->getAttribute('bypassFloodgate')) {
|
||||||
$this->floodgate->assertNotFlooding($actor);
|
$this->floodgate->assertNotFlooding($actor);
|
||||||
|
|
|
@ -29,6 +29,7 @@ use Flarum\Locale\LocaleManager;
|
||||||
use Flarum\Settings\Event\Saved;
|
use Flarum\Settings\Event\Saved;
|
||||||
use Flarum\Settings\Event\Saving;
|
use Flarum\Settings\Event\Saving;
|
||||||
use Flarum\Settings\SettingsRepositoryInterface;
|
use Flarum\Settings\SettingsRepositoryInterface;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
use Laminas\Stratigility\MiddlewarePipe;
|
use Laminas\Stratigility\MiddlewarePipe;
|
||||||
use Symfony\Component\Translation\TranslatorInterface;
|
use Symfony\Component\Translation\TranslatorInterface;
|
||||||
|
|
||||||
|
@ -57,6 +58,7 @@ class ForumServiceProvider extends AbstractServiceProvider
|
||||||
$this->app->singleton('flarum.forum.middleware', function () {
|
$this->app->singleton('flarum.forum.middleware', function () {
|
||||||
return [
|
return [
|
||||||
'flarum.forum.error_handler',
|
'flarum.forum.error_handler',
|
||||||
|
'flarum.forum.proxy_middleware',
|
||||||
HttpMiddleware\ParseJsonBody::class,
|
HttpMiddleware\ParseJsonBody::class,
|
||||||
HttpMiddleware\CollectGarbage::class,
|
HttpMiddleware\CollectGarbage::class,
|
||||||
HttpMiddleware\StartSession::class,
|
HttpMiddleware\StartSession::class,
|
||||||
|
@ -76,6 +78,15 @@ class ForumServiceProvider extends AbstractServiceProvider
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$this->app->bind('flarum.forum.proxy_middleware', function () {
|
||||||
|
$config = $this->app->make('flarum.config');
|
||||||
|
|
||||||
|
return new HttpMiddleware\ProxyAddress(
|
||||||
|
Arr::get($config, 'reverse_proxy.enabled', false),
|
||||||
|
Arr::get($config, 'reverse_proxy.allowed', ['127.0.0.1'])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
$this->app->singleton('flarum.forum.handler', function () {
|
$this->app->singleton('flarum.forum.handler', function () {
|
||||||
$pipe = new MiddlewarePipe;
|
$pipe = new MiddlewarePipe;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* For detailed copyright and license information, please view the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Http\Exception;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Flarum\Foundation\KnownError;
|
||||||
|
|
||||||
|
class ProxyNotAllowedException extends Exception implements KnownError
|
||||||
|
{
|
||||||
|
public function getType(): string
|
||||||
|
{
|
||||||
|
return 'reverse_proxy_not_allowed';
|
||||||
|
}
|
||||||
|
}
|
72
framework/core/src/Http/Middleware/ProxyAddress.php
Normal file
72
framework/core/src/Http/Middleware/ProxyAddress.php
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* For detailed copyright and license information, please view the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Http\Middleware;
|
||||||
|
|
||||||
|
use Flarum\Http\Exception\ProxyNotAllowedException;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\MiddlewareInterface as Middleware;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
class ProxyAddress implements Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $allowedAddresses;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $enabled
|
||||||
|
* @param array $allowedAddresses
|
||||||
|
*/
|
||||||
|
public function __construct($enabled, $allowedAddresses)
|
||||||
|
{
|
||||||
|
$this->enabled = $enabled;
|
||||||
|
$this->allowedAddresses = $allowedAddresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function wildcardMatch(string $ipAddress): bool
|
||||||
|
{
|
||||||
|
foreach ($this->allowedAddresses as $allowedAddress) {
|
||||||
|
if (fnmatch($allowedAddress, $ipAddress)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||||
|
{
|
||||||
|
$serverParams = $request->getServerParams();
|
||||||
|
$ipAddress = Arr::get($serverParams, 'REMOTE_ADDR', '127.0.0.1');
|
||||||
|
|
||||||
|
if ($this->enabled) {
|
||||||
|
if ($this->wildcardMatch($ipAddress)) {
|
||||||
|
// standard header for proxies, see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For
|
||||||
|
$ipAddress = Arr::get($serverParams, 'X_FORWARDED_FOR', $ipAddress);
|
||||||
|
$ipAddress = Arr::get($serverParams, 'HTTP_CLIENT_IP', $ipAddress);
|
||||||
|
$ipAddress = Arr::get($serverParams, 'X_PROXYUSER_IP', $ipAddress);
|
||||||
|
} else {
|
||||||
|
throw new ProxyNotAllowedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = $request->withAttribute('ipAddress', $ipAddress);
|
||||||
|
|
||||||
|
return $handler->handle($request);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user