Skip to content

Commit

Permalink
Add cloud ip bans to BouncerService
Browse files Browse the repository at this point in the history
  • Loading branch information
dansup committed Apr 20, 2023
1 parent d878672 commit 50ab2e2
Show file tree
Hide file tree
Showing 10 changed files with 401 additions and 3 deletions.
205 changes: 205 additions & 0 deletions app/Http/Controllers/Api/ApiV1Controller.php

Large diffs are not rendered by default.

65 changes: 62 additions & 3 deletions app/Http/Controllers/Api/ApiV1Dot1Controller.php
Expand Up @@ -23,6 +23,7 @@
use App\Services\PublicTimelineService;
use App\Services\NetworkTimelineService;
use App\Util\Lexer\RestrictedNames;
use App\Services\BouncerService;
use App\Services\EmailService;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Hash;
Expand Down Expand Up @@ -65,6 +66,10 @@ public function report(Request $request)
abort_if(!$user, 403);
abort_if($user->status != null, 403);

if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$report_type = $request->input('report_type');
$object_id = $request->input('object_id');
$object_type = $request->input('object_type');
Expand Down Expand Up @@ -168,6 +173,10 @@ public function deleteAvatar(Request $request)
abort_if(!$user, 403);
abort_if($user->status != null, 403);

if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$avatar = $user->profile->avatar;

if( $avatar->media_path == 'public/avatars/default.png' ||
Expand Down Expand Up @@ -204,6 +213,10 @@ public function accountPosts(Request $request, $id)
abort_if(!$user, 403);
abort_if($user->status != null, 403);

if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$account = AccountService::get($id);

if(!$account || $account['username'] !== $request->input('username')) {
Expand Down Expand Up @@ -238,6 +251,9 @@ public function accountChangePassword(Request $request)
$user = $request->user();
abort_if(!$user, 403);
abort_if($user->status != null, 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$this->validate($request, [
'current_password' => 'bail|required|current_password',
Expand Down Expand Up @@ -276,6 +292,9 @@ public function accountLoginActivity(Request $request)
$user = $request->user();
abort_if(!$user, 403);
abort_if($user->status != null, 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}
$agent = new Agent();
$currentIp = $request->ip();

Expand Down Expand Up @@ -314,6 +333,10 @@ public function accountTwoFactor(Request $request)
abort_if(!$user, 403);
abort_if($user->status != null, 403);

if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$res = [
'active' => (bool) $user->{'2fa_enabled'},
'setup_at' => $user->{'2fa_setup_at'}
Expand All @@ -331,6 +354,9 @@ public function accountEmailsFromPixelfed(Request $request)
$user = $request->user();
abort_if(!$user, 403);
abort_if($user->status != null, 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}
$from = config('mail.from.address');

$emailVerifications = EmailVerification::whereUserId($user->id)
Expand Down Expand Up @@ -404,6 +430,10 @@ public function accountApps(Request $request)
abort_if(!$user, 403);
abort_if($user->status != null, 403);

if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$res = $user->tokens->sortByDesc('created_at')->take(10)->map(function($token, $key) use($request) {
return [
'id' => $token->id,
Expand All @@ -422,17 +452,20 @@ public function accountApps(Request $request)
public function inAppRegistrationPreFlightCheck(Request $request)
{
return [
'open' => config('pixelfed.open_registration'),
'open' => config_cache('pixelfed.open_registration'),
'iara' => config('pixelfed.allow_app_registration')
];
}

public function inAppRegistration(Request $request)
{
abort_if($request->user(), 404);
abort_unless(config('pixelfed.open_registration'), 404);
abort_unless(config_cache('pixelfed.open_registration'), 404);
abort_unless(config('pixelfed.allow_app_registration'), 404);
abort_unless($request->hasHeader('X-PIXELFED-APP'), 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}
$this->validate($request, [
'email' => [
'required',
Expand Down Expand Up @@ -530,6 +563,9 @@ public function inAppRegistrationEmailRedirect(Request $request)
'ut' => 'required',
'rt' => 'required'
]);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}
$ut = $request->input('ut');
$rt = $request->input('rt');
$url = 'pixelfed://confirm-account/'. $ut . '?rt=' . $rt;
Expand All @@ -539,9 +575,12 @@ public function inAppRegistrationEmailRedirect(Request $request)
public function inAppRegistrationConfirm(Request $request)
{
abort_if($request->user(), 404);
abort_unless(config('pixelfed.open_registration'), 404);
abort_unless(config_cache('pixelfed.open_registration'), 404);
abort_unless(config('pixelfed.allow_app_registration'), 404);
abort_unless($request->hasHeader('X-PIXELFED-APP'), 403);
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}
$this->validate($request, [
'user_token' => 'required',
'random_token' => 'required',
Expand Down Expand Up @@ -578,6 +617,10 @@ public function archive(Request $request, $id)
{
abort_if(!$request->user(), 403);

if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$status = Status::whereNull('in_reply_to_id')
->whereNull('reblog_of_id')
->whereProfileId($request->user()->profile_id)
Expand Down Expand Up @@ -606,6 +649,10 @@ public function unarchive(Request $request, $id)
{
abort_if(!$request->user(), 403);

if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$status = Status::whereNull('in_reply_to_id')
->whereNull('reblog_of_id')
->whereProfileId($request->user()->profile_id)
Expand Down Expand Up @@ -633,6 +680,10 @@ public function archivedPosts(Request $request)
{
abort_if(!$request->user(), 403);

if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$statuses = Status::whereProfileId($request->user()->profile_id)
->whereScope('archived')
->orderByDesc('id')
Expand All @@ -645,6 +696,10 @@ public function placesById(Request $request, $id, $slug)
{
abort_if(!$request->user(), 403);

if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$place = Place::whereSlug($slug)->findOrFail($id);

$posts = Cache::remember('pf-api:v1.1:places-by-id:' . $place->id, 3600, function() use($place) {
Expand Down Expand Up @@ -680,6 +735,10 @@ public function moderatePost(Request $request, $id)
abort_if(!$request->user(), 403);
abort_if($request->user()->is_admin != true, 403);

if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$this->validate($request, [
'action' => 'required|in:cw,mark-public,mark-unlisted,mark-private,mark-spammer,delete'
]);
Expand Down
31 changes: 31 additions & 0 deletions app/Http/Controllers/Auth/ForgotPasswordController.php
Expand Up @@ -4,6 +4,8 @@

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use App\Services\BouncerService;
use Illuminate\Http\Request;

class ForgotPasswordController extends Controller
{
Expand All @@ -29,4 +31,33 @@ public function __construct()
{
$this->middleware('guest');
}

/**
* Display the form to request a password reset link.
*
* @return \Illuminate\View\View
*/
public function showLinkRequestForm()
{
if(config('pixelfed.bouncer.cloud_ips.ban_logins')) {
abort_if(BouncerService::checkIp(request()->ip()), 404);
}

return view('auth.passwords.email');
}

/**
* Validate the email for the given request.
*
* @param \Illuminate\Http\Request $request
* @return void
*/
protected function validateEmail(Request $request)
{
if(config('pixelfed.bouncer.cloud_ips.ban_logins')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$request->validate(['email' => 'required|email']);
}
}
14 changes: 14 additions & 0 deletions app/Http/Controllers/Auth/LoginController.php
Expand Up @@ -6,6 +6,7 @@
use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use App\Services\BouncerService;

class LoginController extends Controller
{
Expand Down Expand Up @@ -42,6 +43,15 @@ public function __construct()
$this->middleware('guest')->except('logout');
}

public function showLoginForm()
{
if(config('pixelfed.bouncer.cloud_ips.ban_logins')) {
abort_if(BouncerService::checkIp(request()->ip()), 404);
}

return view('auth.login');
}

/**
* Validate the user login request.
*
Expand All @@ -51,6 +61,10 @@ public function __construct()
*/
public function validateLogin($request)
{
if(config('pixelfed.bouncer.cloud_ips.ban_logins')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$rules = [
$this->username() => 'required|email',
'password' => 'required|string|min:6',
Expand Down
8 changes: 8 additions & 0 deletions app/Http/Controllers/Auth/RegisterController.php
Expand Up @@ -12,6 +12,7 @@
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\Request;
use App\Services\EmailService;
use App\Services\BouncerService;

class RegisterController extends Controller
{
Expand Down Expand Up @@ -173,6 +174,9 @@ protected function create(array $data)
public function showRegistrationForm()
{
if(config_cache('pixelfed.open_registration')) {
if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp(request()->ip()), 404);
}
$limit = config('pixelfed.max_users');
if($limit) {
abort_if($limit <= User::count(), 404);
Expand All @@ -195,6 +199,10 @@ public function register(Request $request)
{
abort_if(config_cache('pixelfed.open_registration') == false, 400);

if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$count = User::count();
$limit = config('pixelfed.max_users');

Expand Down
50 changes: 50 additions & 0 deletions app/Http/Controllers/Auth/ResetPasswordController.php
Expand Up @@ -4,6 +4,9 @@

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Support\Facades\Password;
use Illuminate\Http\Request;
use App\Services\BouncerService;

class ResetPasswordController extends Controller
{
Expand Down Expand Up @@ -36,4 +39,51 @@ public function __construct()
{
$this->middleware('guest');
}

/**
* Display the password reset view for the given token.
*
* If no token is present, display the link request form.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function showResetForm(Request $request)
{
if(config('pixelfed.bouncer.cloud_ips.ban_logins')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$token = $request->route()->parameter('token');

return view('auth.passwords.reset')->with(
['token' => $token, 'email' => $request->email]
);
}

public function reset(Request $request)
{
if(config('pixelfed.bouncer.cloud_ips.ban_logins')) {
abort_if(BouncerService::checkIp($request->ip()), 404);
}

$request->validate($this->rules(), $this->validationErrorMessages());

// Here we will attempt to reset the user's password. If it is successful we
// will update the password on an actual user model and persist it to the
// database. Otherwise we will parse the error and return the response.
$response = $this->broker()->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
}
);

// If the password was successfully reset, we will redirect the user back to
// the application's home authenticated view. If there is an error we can
// redirect them back to where they came from with their error message.
return $response == Password::PASSWORD_RESET
? $this->sendResetResponse($request, $response)
: $this->sendResetFailedResponse($request, $response);
}

}
20 changes: 20 additions & 0 deletions app/Services/BouncerService.php
@@ -0,0 +1,20 @@
<?php

namespace App\Services;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\IpUtils;

class BouncerService
{
public static function checkIp($ip)
{
$knownCloudCidrs = Cache::rememberForever('pf:bouncer-service:check-ip:known-cloud-cidrs', function() {
$file = Storage::get('bouncer/all.json');
return json_decode($file, true);
});

return IpUtils::checkIp($ip, $knownCloudCidrs);
}
}
7 changes: 7 additions & 0 deletions config/pixelfed.php
Expand Up @@ -259,6 +259,13 @@

'bouncer' => [
'enabled' => env('PF_BOUNCER_ENABLED', false),

'cloud_ips' => [
'ban_logins' => env('PF_BOUNCER_BAN_CLOUD_LOGINS', true),
'ban_signups' => env('PF_BOUNCER_BAN_CLOUD_SIGNUPS', true),
'ban_api' => env('PF_BOUNCER_BAN_CLOUD_API', true),
'ban_api_strict_mode' => env('PF_BOUNCER_BAN_CLOUD_API_STRICT_MODE', true),
],
],

/*
Expand Down

0 comments on commit 50ab2e2

Please sign in to comment.