カテゴリー
IT Tips

Proxyと指定国以外からのアクセスを規制する

#!/usr/bin/php
<?php
/*
 * Author: 十円玉(2018/06/02)
 * Proxyと日本のIP以外弾く.htaccess作るスクリプト。CRONで動かすこと。
 *
 * $htaccess_file:設定を書き込む.htaccessのパス
 * $iplist_url:国コード別IP帯リストのURL
 * $allow_countries:アクセスを許可する国コード
 * $ignore_proxy_elements:アクセスを拒否するProxy環境変数
 * $tmp_ip_list:許可した国の全IP帯
 * $allow_lists:アクセス許可国のIP帯
 * $allow_ips:上記IP帯を、.htaccessのアクセスルールに直した文字列群
 * $proxy_blocks:Proxyの環境変数をアクセスから除外するためのルール文
 * $fp:ファイルポインタ
 * $write:.htaccessに書き込む内容
*/

/*
 * 初期設定
*/

// .htaccessのパス
$htaccess_file = "/path/to/.htaccess";

// 国コード別IP帯リストのURL
$iplist_url = "http://nami.jp/ipv4bycc/cidr.txt";

// アクセスを許可する国コード
$allow_countries = "JP"; // JP|US|DE ←パイプで分ける

// アクセスを拒否するProxy環境変数
$ignore_proxy_elements = array(
	"FORWARDED",
	"FORWARDED-FOR",
	"X-FORWARDED",
	"X_FORWARDED_FOR",
	"HTTP_X_FORWARDED_FOR",
	"VIA",
	"USERAGENT_VIA",
	"XPROXY_CONNECTION",
	"PROXY_CONNECTION",
	"HTTP_PC_REMOTE_ADDR",
	"HTTP_CLIENT_IP",
);

/*
 * 初期設定はここまで
*/

// 全世界のIP帯を取得
$tmp_ip_list = @file_get_contents($iplist_url);

// 上記国コードのIP帯を抜き出す
preg_match_all("/(?:".$allow_countries.")\t(?:[^\t\n]+)/",$tmp_ip_list,$allow_lists);

// 上記IP帯を.htaccessでのアクセス許可文として整形する
$allow_ips = "";
foreach($allow_lists[2] as $val)
{
	$allow_ips.= "Allow from ".$val."\n";
}

// 上記のProxy環境変数を持っていたらアクセス除外するルール文を作成
$proxy_blocks="# block proxy servers\n";
$i=0;
while($i<count($ignore_proxy_elements))
{
	if ($i == (count($ignore_proxy_elements)-1))
	{
		$proxy_blocks.= "RewriteCond %{".$ignore_proxy_elements[$i]."} !^$\n";
	}
	else
	{
		$proxy_blocks.= "RewriteCond %{".$ignore_proxy_elements[$i]."} !^$ [OR]\n";
	}
	$i+=1;
}

$proxy_blocks.= "RewriteRule ^(.*)$ - [F]\n";

// .htaccessを作成して終了
$fp = @fopen($htaccess_file,"w");
$write = "<IfModule mod_rewrite.c>\n";
$write.= "RewriteEngine On\n";
$write.= "RewriteBase /\n";
$write.= $proxy_blocks;
$write.= "Order deny,Allow\n";
$write.= "Deny from all\n";
$write.= $allow_ips;
$write.= "</IfModule>\n";

$fp = @fwrite($fp,$write);
@fclose($fp);
?>

カテゴリー
IT Tips

phpでメールアドレスを簡単にバリデーション

皆さんはネイティブphpで開発をするとき、メールアドレスのバリデーションはどうやっていますか?
正規表現?MXレコードの応答?
いやいや、もっとカンタンな方法がありました。これです。

<?php
/*
 * filter_varの第二引数でメールアドレスのチェックをする方法。
 * メールアドレスの記述が正しければstring型を返し、ダメならFALSEを返します。
 */
private function mail_check($mailaddress="")
{
    if (filter_var($mailaddress, FILTER_VALIDATE_EMAIL)===FALSE)
    {
        return FALSE;
    }
    else
    {
        return TRUE;
    }
}
?>

しかし2009年以前のDoCoMoのEメールアドレスはRFCに準拠しておりません。
その場合どうしても正規表現じゃなければダメだ!というのなら、このサイトを参考にしなさい。

[amazon_link asins=’479813547X,4798052582′ template=’SupportedAMP’ store=’10yendama-22′ marketplace=’JP’ link_id=’e9df86ae-2705-11e8-8d38-7b4db5ed6472′]

カテゴリー
IT Tips

アクセス解析を追加してみた(THK Analytics)

GoogleAnalyticsがあれば大抵のアクセス統計は取れますが、生ログが欲しいといった場合やサーバログの統計が面倒・見づらいといった場合がありますよね。
WordPressのJetPackについているアクセス解析なんかもいいですが、JetPack自体がサイトを重たくするので使いたくありいません(´・ω・`)
そこで今日から、外部アクセス解析スクリプトである「THK Analytics」を実験的に導入してみました。↓

結構見やすくていいですよ。

カテゴリー
IT Tips

Digest認証のパスワードファイルを作成するphpスクリプト

通常、レンタルサーバ等では管理画面よりBasic認証に必要なためのファイルを作ることが出来ますが
Basic認証よりセキュアなDigest認証を公式にサポートしていないサーバが多いと思います。
然しSSHがない環境でも、phpでDigest認証のパスワードを作ることが出来ます。

Digest認証については、Basic認証よりセキュアなDigest認証を使う方法を参照のこと。

下記PHPは取扱に注意すること。
# /path/to/htdigest.php

#!/usr/bin/php
<?php
/*
 * This script is create Digest Authentication files.
 */

// ".htdigest"'s path
$path = "/path/to/.htdigest";

// Common realms
$realm = array(
    0 => "This contents can join at Administrators only.",
    1 => "Members only.",
);
 
// Login users setting
$users = array(
    0=>array(
        "name"     => "admin",
        "realm"    => $realm[0],
        "password" => "adminpassword",
    ),
    1=>array(
        "name" => "member",
        "realm" => $realm[1],
        "password" => "memberpassword",
    ),
);
 // Create Crypted password
foreach ($users as $val)
{
    $put[] = sprintf('%s:%s:%s',$val["name"],$val["realm"],md5(sprintf('%s:%s:%s',$val["name"],$val["realm"],$val["password"])));
}

// Create .htdigest
$fp = @fopen($path,"w");
@($fp,implode("\n",$put)."\n");
@fclose($fp);
?>

.htaccessによる認証の分け方+Digest認証の設定方法

# Administrator's contents
<Location "/members/admin">
    AuthType Digest
    AuthName "This contents can join at Administrators only."
    AuthUserFile /path/to/.htdigest
    Require valid-user
</Location>

# Members's contents
<Location "/members/public">
    AuthType Digest
    AuthName "Members only."
    AuthUserFile /path/to/.htdigest
    Require valid-user
</Location>

[amazon_link asins=’479813547X’ template=’SupportedAMP’ store=’10yendama-22′ marketplace=’JP’ link_id=’e81d9941-270a-11e8-80ea-f3b12e7f838b’]

カテゴリー
IT Tips

phper2~3年目ぐらいには何かMVCフレームワークをマスターしておこう的なお話

下記phpソースコードは、架空のWebシステムのログインユーザ登録+編集スクリプトを簡易化したもの。
よくモデルや拡張の使い方を知らんで結局ネイティブコーディングしている人がいますが、設計段階で準備していればこんなカンタンに済むんだよ的なイヤミソースです。

<?php
class User extends Ex_Controller
{
	function __construct()
	{
		parent::__construct();
		
		$db        = $this->StdDatabase();
		$user_data = $this->session;
		$post_data = $this->input->post();
		$err       = (object) array();
	}
	
	// Method
	public function __remap($method="index")
	{
	
		// Run validation
		$err->input = $this->Validator->user($post_data);

		// Validation error
		if (empty($err->input)===FALSE)
		{
			$this->view->error("Validation error.", $err->input,false);
		}

		// User actions
		switch ($method)
		{
			// regist user
			case "register":
			{
				if ($user_data->level > 2)
				{
					$col = $db->user->getColumn();
					
					foreach ($col as $key=>$val)
					{
						$col->$key = $post_data->register->$key;
					}
					
					$set = $db->user->Regist($col,$err->regist);
					
					if (empty($err->regist)===FALSE)
					{
						$this->view->error("Database error.", $err->regist, false);
					}
					else
					{
						$this->view->user("regist", 1, true);
					}
				}
				else
				{
					$this->view->error("Permission error.", "You do not have a permission of regist user.", false);
				}
				
				break;
			}
			
			// edit + delete user
			case "edit":
			{
				if ($user_data->level > 3)
				{
					$col = $db->user->getColumn();
					
					foreach ($col as $key=>$val)
					{
						$col->$key = $post_data->edit->$key;
					}
					
					$set = $db->user->Edit($col,$err->edit);
					
					if (empty($err->edit)===FALSE)
					{
						$this->view->error("Database error.", $err->edit,false);
					}
					else
					{
						$this->view->user("edit",$col->act, true);
					}
				}
				else
				{
					$this->view->error("Permission error.", "You do not have a permission of edit user.", false);
				}
				
				break;
			}
			
			// Default (return index)
			default:
			{
				$this->view->user("index", 1, true);
			}
		}
	}
}