Skip to content

Commit

Permalink
Add AccessBlock class/test fc2blog#291
Browse files Browse the repository at this point in the history
  • Loading branch information
uzulla committed Aug 9, 2021
1 parent a79a49e commit 3a2aaf3
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/app/temp/debug_html/*
/app/temp/log/*
/app/temp/installed.lock
/app/temp/GeoLite2-Country.mmdb
/app/temp/github_release_cache.json
/app/version
/app/vendor/
Expand Down
4 changes: 4 additions & 0 deletions app/config.sample.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
// ログイン時にメール認証を有効化するか
define("MFA_EMAIL", "0");

// 国コード(ISO Code)指定でアクセスブロック
//define("USER_BLOCK_COUNTRY_ISO_CODE_CSV", "JP");
//define("ADMIN_BLOCK_COUNTRY_ISO_CODE_CSV", "JP,US");

// If you want get error log on display.
// define('ERROR_ON_DISPLAY', "1");
// ini_set('display_errors', '1');
Expand Down
4 changes: 4 additions & 0 deletions app/config_read_from_env.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
define("EMERGENCY_PASSWORD_RESET_ENABLE", (string)getenv("FC2_EMERGENCY_PASSWORD_RESET_ENABLE"));
define("MFA_EMAIL", (string)getenv("FC2_MFA_EMAIL"));

// 国コード(ISO Code)指定でアクセスブロック
define("USER_BLOCK_COUNTRY_ISO_CODE_CSV", (string)getenv("FC2_USER_BLOCK_COUNTRY_ISO_CODE_CSV"));
define("ADMIN_BLOCK_COUNTRY_ISO_CODE_CSV", (string)getenv("FC2_ADMIN_BLOCK_COUNTRY_ISO_CODE_CSV"));

if (strlen((string)getenv("FC2_GITHUB_REPO")) > 0) {
define("GITHUB_REPO", (string)getenv("FC2_GITHUB_REPO"));
}
96 changes: 96 additions & 0 deletions app/src/Service/AccessBlock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php
declare(strict_types=1);

namespace Fc2blog\Service;

use Exception;
use Fc2blog\App;
use Fc2blog\Web\Request;
use MaxMind\Db\Reader;

class AccessBlock
{
const MMDB_FILE_PATH = App::TEMP_DIR . "/GeoLite2-Country.mmdb";

private $user_block_country_iso_code_csv;
private $admin_block_country_iso_code_csv;

public function __construct(
string $user_block_country_iso_code_csv = "",
string $admin_block_country_iso_code_csv = ""
)
{
if (strlen($user_block_country_iso_code_csv) > 0) {
$this->user_block_country_iso_code_csv = $user_block_country_iso_code_csv;
} elseif (defined("USER_BLOCK_COUNTRY_ISO_CODE_CSV")) {
$this->user_block_country_iso_code_csv = USER_BLOCK_COUNTRY_ISO_CODE_CSV;
} else {
$this->user_block_country_iso_code_csv = "";
}

if (strlen($admin_block_country_iso_code_csv) > 0) {
$this->admin_block_country_iso_code_csv = $admin_block_country_iso_code_csv;
} elseif (defined("ADMIN_BLOCK_COUNTRY_ISO_CODE_CSV")) {
$this->admin_block_country_iso_code_csv = ADMIN_BLOCK_COUNTRY_ISO_CODE_CSV;
} else {
$this->admin_block_country_iso_code_csv = "";
}

}

public function isAdminBlockIp(Request $request): bool
{
if (strlen($this->admin_block_country_iso_code_csv) === 0) return false;
/** @noinspection PhpUnhandledExceptionInspection */ // エラーなら、アプリは停止で良い
return $this->isBlockIp($request, $this->admin_block_country_iso_code_csv);
}

public function isUserBlockIp(Request $request): bool
{
if (strlen($this->user_block_country_iso_code_csv) === 0) return false;
/** @noinspection PhpUnhandledExceptionInspection */ // エラーなら、アプリは停止で良い
return $this->isBlockIp($request, $this->user_block_country_iso_code_csv);
}

/**
* Check IP address that have to blocked with Read MaxMind Geo ip database.
* @param Request $request
* @param string $block_country_iso_code_csv
* @return bool
* @throws Reader\InvalidDatabaseException
* @throws Exception
*/
public function isBlockIp(Request $request, string $block_country_iso_code_csv): bool
{
if (
!file_exists(self::MMDB_FILE_PATH) ||
!is_file(self::MMDB_FILE_PATH) ||
!is_readable(self::MMDB_FILE_PATH)
) {
// mmdb file notfound. Not to be checking. Done.
return false;
}

$reader = new Reader(self::MMDB_FILE_PATH);
$result = $reader->get($request->getClientIpAddress());
$reader->close();
if (
!is_array($result) || // If undetermined, Result will be null.
!isset($result['country']) ||
!isset($result['country']['iso_code'])
) {
// Could not detect country information. So allow access.
return false;
}

$determined_country_iso_code = $result['country']['iso_code'];

return $this->isContainCsv($determined_country_iso_code, $block_country_iso_code_csv);
}

private function isContainCsv(string $country_iso_code, string $block_country_iso_code_csv): bool
{
$list = explode(',', $block_country_iso_code_csv);
return in_array($country_iso_code, $list);
}
}
34 changes: 34 additions & 0 deletions tests/App/Service/AccessBlockTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);

namespace Fc2blog\Tests\App\Service;

use Fc2blog\Service\AccessBlock;
use Fc2blog\Web\Request;
use PHPUnit\Framework\TestCase;

class AccessBlockTest extends TestCase
{
public function testAccessBlock(): void
{
$jp_ip_address = "133.0.0.1"; // Some JP address https://www.nic.ad.jp/ja/dns/jp-addr-block.html
$r = new Request(null, null, null, null, null, null, [
'REMOTE_ADDR' => $jp_ip_address
]);

$ab = new AccessBlock("JP");
$this->assertTrue($ab->isUserBlockIp($r));

$ab = new AccessBlock("JP,US");
$this->assertTrue($ab->isUserBlockIp($r));

$ab = new AccessBlock("US,JP");
$this->assertTrue($ab->isUserBlockIp($r));

$ab = new AccessBlock("US");
$this->assertFalse($ab->isUserBlockIp($r));

$ab = new AccessBlock();
$this->assertFalse($ab->isUserBlockIp($r));
}
}

0 comments on commit 3a2aaf3

Please sign in to comment.