You've already forked Atomcms-edit
440 lines
19 KiB
PHP
Executable File
440 lines
19 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Filament\Pages\VPN;
|
|
|
|
use App\Models\Miscellaneous\WebsiteBlockedCountry;
|
|
use App\Models\Miscellaneous\WebsiteIpBlacklist;
|
|
use App\Models\Miscellaneous\WebsiteIpWhitelist;
|
|
use App\Models\Miscellaneous\WebsiteSetting;
|
|
use App\Services\IpLookupService;
|
|
use Filament\Actions\Action;
|
|
use Filament\Forms\Components\Select;
|
|
use Filament\Forms\Components\TextInput;
|
|
use Filament\Forms\Components\Toggle;
|
|
use Filament\Forms\Concerns\InteractsWithForms;
|
|
use Filament\Forms\Contracts\HasForms;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Pages\Page;
|
|
use Filament\Schemas\Components\Section;
|
|
use Filament\Schemas\Components\Tabs;
|
|
use Filament\Schemas\Components\Tabs\Tab;
|
|
use Filament\Schemas\Schema;
|
|
use Filament\Tables\Columns\TextColumn;
|
|
|
|
final class VPNManagement extends Page implements HasForms
|
|
{
|
|
use InteractsWithForms;
|
|
|
|
#[\Override]
|
|
protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-shield-exclamation';
|
|
|
|
#[\Override]
|
|
protected static string|\UnitEnum|null $navigationGroup = 'Website';
|
|
|
|
#[\Override]
|
|
protected static ?string $navigationLabel = 'VPN Beheer';
|
|
|
|
#[\Override]
|
|
protected static ?string $title = 'VPN & IP Beheer';
|
|
|
|
#[\Override]
|
|
protected string $view = 'filament.pages.vpn.vpn-management';
|
|
|
|
/** @var array<string, mixed> */
|
|
public array $data = [];
|
|
|
|
public $blockedCountries;
|
|
|
|
public $whitelistedIps;
|
|
|
|
public $blacklistedIps;
|
|
|
|
public $blocklistStats;
|
|
|
|
public function mount(): void
|
|
{
|
|
$this->fillForm();
|
|
$this->loadData();
|
|
}
|
|
|
|
protected function loadData(): void
|
|
{
|
|
$this->blockedCountries = WebsiteBlockedCountry::orderBy('country_name')->get();
|
|
$this->whitelistedIps = WebsiteIpWhitelist::orderBy('created_at', 'desc')->get();
|
|
$this->blacklistedIps = WebsiteIpBlacklist::orderBy('created_at', 'desc')->get();
|
|
|
|
$ipService = new IpLookupService('');
|
|
$this->blocklistStats = $ipService->getBlocklistStats();
|
|
}
|
|
|
|
protected function fillForm(): void
|
|
{
|
|
$this->data = [
|
|
'vpn_block_enabled' => $this->getSettingBool('vpn_block_enabled'),
|
|
'country_block_enabled' => $this->getSettingBool('country_block_enabled'),
|
|
'block_vpn' => $this->getSettingBool('block_vpn'),
|
|
'block_tor' => $this->getSettingBool('block_tor'),
|
|
'block_malicious' => $this->getSettingBool('block_malicious'),
|
|
];
|
|
}
|
|
|
|
protected function getSetting(string $key, string $default = ''): string
|
|
{
|
|
return WebsiteSetting::where('key', $key)->first()?->value ?? $default;
|
|
}
|
|
|
|
protected function getSettingBool(string $key): bool
|
|
{
|
|
return WebsiteSetting::where('key', $key)->first()?->value === '1';
|
|
}
|
|
|
|
public function form(Schema $schema): Schema
|
|
{
|
|
return $schema
|
|
->components([
|
|
Tabs::make('VPN Beheer')
|
|
->tabs([
|
|
Tab::make('Instellingen')
|
|
->icon('heroicon-o-cog-6-tooth')
|
|
->schema([
|
|
Section::make('Gratis Blokkering (Onbeperkt)')
|
|
->description('Gebruikt gratis community blocklists - geen API keys nodig')
|
|
->schema([
|
|
Toggle::make('data.vpn_block_enabled')
|
|
->label('VPN/TOR/Proxy Blokker Actief')
|
|
->helperText('Blokkeer VPN, TOR exit nodes, proxies en bekende malicious IPs'),
|
|
]),
|
|
Section::make('Wat blokkeren?')
|
|
->schema([
|
|
Toggle::make('data.block_vpn')
|
|
->label('VPN & Proxies')
|
|
->helperText('FireHol blocklist'),
|
|
Toggle::make('data.block_tor')
|
|
->label('TOR Exit Nodes')
|
|
->helperText('Alle bekende TOR exit nodes'),
|
|
Toggle::make('data.block_malicious')
|
|
->label('Malicious IPs')
|
|
->helperText('Bekende kwaadwillende IPs uit community databases'),
|
|
]),
|
|
Section::make('Land Blokkering')
|
|
->schema([
|
|
Toggle::make('data.country_block_enabled')
|
|
->label('Land Blokkering Actief')
|
|
->helperText('Sta alleen bezoekers uit toegestane landen toe'),
|
|
]),
|
|
]),
|
|
Tab::make('Geblokkeerde Landen')
|
|
->icon('heroicon-o-globe-alt')
|
|
->schema([
|
|
Section::make('Land toevoegen')
|
|
->schema([
|
|
Select::make('country_to_block')
|
|
->label('Selecteer Land')
|
|
->options($this->getCountryOptions())
|
|
->searchable()
|
|
->placeholder('Kies een land'),
|
|
Action::make('addCountry')
|
|
->label('Blokkeer Land')
|
|
->action('addBlockedCountry')
|
|
->color('danger'),
|
|
]),
|
|
]),
|
|
Tab::make('Whitelist')
|
|
->icon('heroicon-o-check-circle')
|
|
->schema([
|
|
Section::make('Whitelist toevoegen')
|
|
->schema([
|
|
TextInput::make('whitelist_ip')
|
|
->label('IP Adres')
|
|
->placeholder('192.168.1.1'),
|
|
TextInput::make('whitelist_asn')
|
|
->label('ASN')
|
|
->placeholder('AS15169'),
|
|
Select::make('whitelist_country')
|
|
->label('Land')
|
|
->options($this->getCountryOptions())
|
|
->searchable(),
|
|
Action::make('addToWhitelist')
|
|
->label('Toevoegen')
|
|
->action('addToWhitelist')
|
|
->color('success'),
|
|
]),
|
|
]),
|
|
Tab::make('Blacklist')
|
|
->icon('heroicon-o-x-circle')
|
|
->schema([
|
|
Section::make('Blacklist toevoegen')
|
|
->schema([
|
|
TextInput::make('blacklist_ip')
|
|
->label('IP Adres')
|
|
->placeholder('192.168.1.1'),
|
|
TextInput::make('blacklist_asn')
|
|
->label('ASN')
|
|
->placeholder('AS15169'),
|
|
Select::make('blacklist_country')
|
|
->label('Land')
|
|
->options($this->getCountryOptions())
|
|
->searchable(),
|
|
Action::make('addToBlacklist')
|
|
->label('Toevoegen')
|
|
->action('addToBlacklist')
|
|
->color('danger'),
|
|
]),
|
|
]),
|
|
Tab::make('IP Lookup')
|
|
->icon('heroicon-o-magnifying-glass')
|
|
->schema([
|
|
Section::make('IP Opzoeken')
|
|
->schema([
|
|
TextInput::make('lookup_ip')
|
|
->label('IP Adres')
|
|
->placeholder('Voer IP in om te controleren'),
|
|
Action::make('lookupIp')
|
|
->label('Controleer')
|
|
->action('lookupIp')
|
|
->color('info'),
|
|
]),
|
|
]),
|
|
Tab::make('Blocklist Stats')
|
|
->icon('heroicon-o-chart-bar')
|
|
->schema([
|
|
Section::make('Huidige Blocklists')
|
|
->description('Deze lijsten worden automatisch gedownload en dagelijks ververst')
|
|
->schema([
|
|
TextColumn::make('type')->label('Type'),
|
|
TextColumn::make('count')->label('Aantal IPs'),
|
|
]),
|
|
]),
|
|
]),
|
|
])
|
|
->statePath('data');
|
|
}
|
|
|
|
protected function getCountryOptions(): array
|
|
{
|
|
return [
|
|
'AD' => 'Andorra', 'AE' => 'United Arab Emirates', 'AF' => 'Afghanistan',
|
|
'AG' => 'Antigua and Barbuda', 'AI' => 'Anguilla', 'AL' => 'Albania',
|
|
'AM' => 'Armenia', 'AO' => 'Angola', 'AR' => 'Argentina',
|
|
'AT' => 'Austria', 'AU' => 'Australia', 'AW' => 'Aruba',
|
|
'AZ' => 'Azerbaijan', 'BA' => 'Bosnia and Herzegovina', 'BB' => 'Barbados',
|
|
'BD' => 'Bangladesh', 'BE' => 'Belgium', 'BG' => 'Bulgaria',
|
|
'BH' => 'Bahrain', 'BI' => 'Burundi', 'BJ' => 'Benin',
|
|
'BM' => 'Bermuda', 'BN' => 'Brunei', 'BO' => 'Bolivia',
|
|
'BR' => 'Brazil', 'BS' => 'Bahamas', 'BT' => 'Bhutan',
|
|
'BW' => 'Botswana', 'BY' => 'Belarus', 'BZ' => 'Belize',
|
|
'CA' => 'Canada', 'CH' => 'Switzerland', 'CL' => 'Chile',
|
|
'CN' => 'China', 'CO' => 'Colombia', 'CR' => 'Costa Rica',
|
|
'CU' => 'Cuba', 'CY' => 'Cyprus', 'CZ' => 'Czechia',
|
|
'DE' => 'Germany', 'DK' => 'Denmark', 'DO' => 'Dominican Republic',
|
|
'DZ' => 'Algeria', 'EC' => 'Ecuador', 'EE' => 'Estonia',
|
|
'EG' => 'Egypt', 'ES' => 'Spain', 'ET' => 'Ethiopia',
|
|
'FI' => 'Finland', 'FJ' => 'Fiji', 'FR' => 'France',
|
|
'GB' => 'United Kingdom', 'GD' => 'Grenada', 'GE' => 'Georgia',
|
|
'GH' => 'Ghana', 'GI' => 'Gibraltar', 'GL' => 'Greenland',
|
|
'GM' => 'Gambia', 'GN' => 'Guinea', 'GR' => 'Greece',
|
|
'GT' => 'Guatemala', 'HK' => 'Hong Kong', 'HN' => 'Honduras',
|
|
'HR' => 'Croatia', 'HU' => 'Hungary', 'ID' => 'Indonesia',
|
|
'IE' => 'Ireland', 'IL' => 'Israel', 'IN' => 'India',
|
|
'IQ' => 'Iraq', 'IR' => 'Iran', 'IS' => 'Iceland',
|
|
'IT' => 'Italy', 'JM' => 'Jamaica', 'JO' => 'Jordan',
|
|
'JP' => 'Japan', 'KE' => 'Kenya', 'KH' => 'Cambodia',
|
|
'KR' => 'South Korea', 'KW' => 'Kuwait', 'KZ' => 'Kazakhstan',
|
|
'LA' => 'Laos', 'LB' => 'Lebanon', 'LK' => 'Sri Lanka',
|
|
'LT' => 'Lithuania', 'LU' => 'Luxembourg', 'LV' => 'Latvia',
|
|
'MA' => 'Morocco', 'MC' => 'Monaco', 'MD' => 'Moldova',
|
|
'ME' => 'Montenegro', 'MG' => 'Madagascar', 'MK' => 'North Macedonia',
|
|
'MM' => 'Myanmar', 'MN' => 'Mongolia', 'MO' => 'Macao',
|
|
'MT' => 'Malta', 'MU' => 'Mauritius', 'MV' => 'Maldives',
|
|
'MX' => 'Mexico', 'MY' => 'Malaysia', 'MZ' => 'Mozambique',
|
|
'NA' => 'Namibia', 'NG' => 'Nigeria', 'NI' => 'Nicaragua',
|
|
'NL' => 'Netherlands', 'NO' => 'Norway', 'NP' => 'Nepal',
|
|
'NZ' => 'New Zealand', 'OM' => 'Oman', 'PA' => 'Panama',
|
|
'PE' => 'Peru', 'PH' => 'Philippines', 'PK' => 'Pakistan',
|
|
'PL' => 'Poland', 'PR' => 'Puerto Rico', 'PT' => 'Portugal',
|
|
'PY' => 'Paraguay', 'QA' => 'Qatar', 'RO' => 'Romania',
|
|
'RS' => 'Serbia', 'RU' => 'Russia', 'RW' => 'Rwanda',
|
|
'SA' => 'Saudi Arabia', 'SC' => 'Seychelles', 'SD' => 'Sudan',
|
|
'SE' => 'Sweden', 'SG' => 'Singapore', 'SI' => 'Slovenia',
|
|
'SK' => 'Slovakia', 'SN' => 'Senegal', 'SO' => 'Somalia',
|
|
'SR' => 'Suriname', 'SV' => 'El Salvador', 'SY' => 'Syria',
|
|
'TH' => 'Thailand', 'TJ' => 'Tajikistan', 'TN' => 'Tunisia',
|
|
'TR' => 'Turkey', 'TT' => 'Trinidad and Tobago', 'TW' => 'Taiwan',
|
|
'TZ' => 'Tanzania', 'UA' => 'Ukraine', 'UG' => 'Uganda',
|
|
'US' => 'United States', 'UY' => 'Uruguay', 'UZ' => 'Uzbekistan',
|
|
'VE' => 'Venezuela', 'VN' => 'Vietnam', 'ZA' => 'South Africa',
|
|
'ZM' => 'Zambia', 'ZW' => 'Zimbabwe',
|
|
];
|
|
}
|
|
|
|
public function save(): void
|
|
{
|
|
$settings = [
|
|
'vpn_block_enabled' => $this->data['vpn_block_enabled'] ? '1' : '0',
|
|
'country_block_enabled' => $this->data['country_block_enabled'] ? '1' : '0',
|
|
'block_vpn' => $this->data['block_vpn'] ?? true ? '1' : '0',
|
|
'block_tor' => $this->data['block_tor'] ?? true ? '1' : '0',
|
|
'block_malicious' => $this->data['block_malicious'] ?? true ? '1' : '0',
|
|
];
|
|
|
|
foreach ($settings as $key => $value) {
|
|
WebsiteSetting::updateOrCreate(['key' => $key], ['value' => $value]);
|
|
}
|
|
|
|
Notification::make()->title(__('Saved'))->success()->send();
|
|
}
|
|
|
|
public function refreshBlocklists(): void
|
|
{
|
|
$ipService = new IpLookupService('');
|
|
$ipService->refreshBlocklists();
|
|
$this->loadData();
|
|
|
|
Notification::make()->title('Blocklists vernieuwd')->success()->send();
|
|
}
|
|
|
|
public function addBlockedCountry(): void
|
|
{
|
|
$countryCode = $this->data['country_to_block'] ?? null;
|
|
if (! $countryCode) {
|
|
Notification::make()->title('Selecteer een land')->danger()->send();
|
|
|
|
return;
|
|
}
|
|
|
|
if (WebsiteBlockedCountry::where('country_code', $countryCode)->exists()) {
|
|
Notification::make()->title('Land is al geblokkeerd')->warning()->send();
|
|
|
|
return;
|
|
}
|
|
|
|
$countries = $this->getCountryOptions();
|
|
$countryCode = (string) $countryCode;
|
|
WebsiteBlockedCountry::create([
|
|
'country_code' => $countryCode,
|
|
'country_name' => $countries[$countryCode] ?? $countryCode,
|
|
]);
|
|
|
|
$this->loadData();
|
|
Notification::make()->title('Land geblokkeerd')->success()->send();
|
|
}
|
|
|
|
public function removeBlockedCountry(int $id): void
|
|
{
|
|
WebsiteBlockedCountry::destroy($id);
|
|
$this->loadData();
|
|
Notification::make()->title('Verwijderd')->success()->send();
|
|
}
|
|
|
|
public function addToWhitelist(): void
|
|
{
|
|
$ip = $this->data['whitelist_ip'] ?? null;
|
|
$asn = $this->data['whitelist_asn'] ?? null;
|
|
$countryCode = $this->data['whitelist_country'] ?? null;
|
|
|
|
if (! $ip && ! $asn && ! $countryCode) {
|
|
Notification::make()->title('Voer IP, ASN of land in')->danger()->send();
|
|
|
|
return;
|
|
}
|
|
|
|
$countries = $this->getCountryOptions();
|
|
$countryCodeStr = (string) ($countryCode ?? '');
|
|
$countryName = $countryCode ? ($countries[$countryCodeStr] ?? null) : null;
|
|
|
|
WebsiteIpWhitelist::create([
|
|
'ip_address' => $ip ?? null,
|
|
'asn' => $asn ?? null,
|
|
'country_code' => $countryCodeStr,
|
|
'country_name' => $countryName,
|
|
'whitelist_asn' => ! empty($asn),
|
|
'whitelist_country' => ! empty($countryCode),
|
|
]);
|
|
|
|
$this->loadData();
|
|
Notification::make()->title('Toegevoegd aan whitelist')->success()->send();
|
|
}
|
|
|
|
public function addToBlacklist(): void
|
|
{
|
|
$ip = $this->data['blacklist_ip'] ?? null;
|
|
$asn = $this->data['blacklist_asn'] ?? null;
|
|
$countryCode = $this->data['blacklist_country'] ?? null;
|
|
|
|
if (! $ip && ! $asn && ! $countryCode) {
|
|
Notification::make()->title('Voer IP, ASN of land in')->danger()->send();
|
|
|
|
return;
|
|
}
|
|
|
|
$countries = $this->getCountryOptions();
|
|
$countryCodeStr = (string) ($countryCode ?? '');
|
|
$countryName = $countryCode ? ($countries[$countryCodeStr] ?? null) : null;
|
|
|
|
WebsiteIpBlacklist::create([
|
|
'ip_address' => $ip ?? null,
|
|
'asn' => $asn ?? null,
|
|
'country_code' => $countryCodeStr,
|
|
'country_name' => $countryName,
|
|
'blacklist_asn' => ! empty($asn),
|
|
'blacklist_country' => ! empty($countryCode),
|
|
]);
|
|
|
|
$this->loadData();
|
|
Notification::make()->title('Toegevoegd aan blacklist')->success()->send();
|
|
}
|
|
|
|
public function removeFromWhitelist(int $id): void
|
|
{
|
|
WebsiteIpWhitelist::destroy($id);
|
|
$this->loadData();
|
|
Notification::make()->title('Verwijderd')->success()->send();
|
|
}
|
|
|
|
public function removeFromBlacklist(int $id): void
|
|
{
|
|
WebsiteIpBlacklist::destroy($id);
|
|
$this->loadData();
|
|
Notification::make()->title('Verwijderd')->success()->send();
|
|
}
|
|
|
|
public function lookupIp(): void
|
|
{
|
|
$ip = $this->data['lookup_ip'] ?? null;
|
|
if (! $ip) {
|
|
Notification::make()->title('Voer een IP in')->danger()->send();
|
|
|
|
return;
|
|
}
|
|
|
|
$ipService = new IpLookupService('');
|
|
$countryInfo = $ipService->getCountryInfo($ip);
|
|
$threatInfo = $ipService->checkVpnProxyTor($ip);
|
|
|
|
$message = "IP: {$ip}\n\n";
|
|
|
|
if (! empty($countryInfo['country_name'])) {
|
|
$message .= "📍 {$countryInfo['country_name']} ({$countryInfo['country_code']})\n";
|
|
$message .= " {$countryInfo['city']} - {$countryInfo['isp']}\n\n";
|
|
}
|
|
|
|
$message .= "🚫 Blokkeren:\n";
|
|
$message .= ' VPN/Proxy: ' . ($threatInfo['is_vpn'] ? 'JA' : 'Nee') . "\n";
|
|
$message .= ' TOR: ' . ($threatInfo['is_tor'] ? 'JA' : 'Nee') . "\n";
|
|
$message .= ' Malicious: ' . ($threatInfo['is_malicious'] ? 'JA' : 'Nee') . "\n";
|
|
|
|
Notification::make()->title('Resultaat')->body($message)->success()->send();
|
|
}
|
|
|
|
#[\Override]
|
|
protected function getActions(): array
|
|
{
|
|
return [
|
|
Action::make('save')->label('Opslaan')->action('save')->color('primary'),
|
|
Action::make('refreshBlocklists')->label('Vernieuw Blocklists')->action('refreshBlocklists')->color('warning'),
|
|
];
|
|
}
|
|
}
|