FreeBSDのシンプルなホットスポット

良い一日。

HotSpotポイントを作成する必要がありました。 UNIXに少し精通している人として、ソフトウェアソリューションを探すことにしました。 さらに、このビジネスのために特別な鉄を購入することはできませんでした。 そして、要件は非常に最小限でした。 つまり、たとえばMcDonnaldsネットワーク上で、WiFiの配布を整理します。 つまり ユーザーが入り、ネットワークに接続して、30分のインターネットを静かに手に入れました。 または15メガバイトのトラフィック。





最初は、ChilliSpot、FreeRadius、EasyHotSpot、およびその他のソリューションをこの問題に適応させようとしました。 私はそれを得なかった。 だからこそ、検索を続けて、 lissyaraによるHotSpotの記事に出会いました 。 そして、これがまさに必要なものであることに気づきました。 スクリプトを少し修正して、ほぼ標準のFreeBSDツールで必要なものを正確に入手しました。



FreeBSD 8.2とポートからインストールされたパッケージを使用しましたが、特定のプログラムを使用しないため、このスキームは他のほとんどのシステムで動作します。



など。 2つのネットワークカードを備えたコンピューターがあり、WiFiアクセスポイントがあります。 鉄には他の要件はありません。

FreeBSD、Apache、PHP、MySQL、ISC-dhcpdがコンピューターにインストールされます。



まず、カーネルを再構築してNATとパイプを有効にして速度を制限する必要があります。

カーネルをアセンブルしてインストールする方法は、Googleで見つけることができます。 ここで、カーネルの構築に使用したパラメーターを示します。



options IPFIREWALL

options IPFIREWALL_DEFAULT_TO_ACCEPT

options IPFIREWALL_FORWARD

options IPFIREWALL_VERBOSE

options IPFIREWALL_VERBOSE_LIMIT=50

options IPFIREWALL_NAT

options LIBALIAS

options ROUTETABLES=2

options DUMMYNET

options HZ="1000"









次に、カーネルを構築した後、Apache、PHP、およびMySQLをインストールする必要があります。 このトピックに関する情報もインターネット上でいっぱいです。このため、ここではこのプロセスを説明しません。



設定をrc.confに書き込みます



defaultrouter="1.1.1.1" # .

gateway_enable="YES" # .



ifconfig_re0="inet 1.1.1.2 netmask 255.255.255.252" # , .

ifconfig_re1="inet 10.128.1.1 netmask 255.255.255.0" # , Wi-Fi .



inetd_enable="YES"

sshd_enable="YES" # SSH

sendmail_enable="NO" # Sendmail



firewall_enable="YES" #

firewall_nat_enable="YES" #

dummynet_enable="YES" # Dummynet. .

firewall_script="/etc/firewall.sh" # .









最初に言及したこの記事の前に読んでいただければ、このスキームの動作原理は明らかです。 そうでない場合は、簡単に説明します。 そのため、Wi-Fiポイントに接続するクライアントは、DHCPを介してIPアドレスを受け取ります。 次に、彼がサイトを開こうとすると、挨拶のあるページがスローされます。 上記の記事では、そのページでログインとパスワードが要求されます。 承認を削除したため、実際には、ページに「アクセス」というボタンが1つしかありません。 次のように実装されます。 ファイアウォールのルールは、リクエストをWebサーバーにリダイレクトするように記述されています。 ページにアクセスして1つのボタンをクリックすると、新しいボタンがファイアウォールルールに追加され、指定したIPを持つユーザーがインターネットにアクセスできるようになります。 cronデーモンは毎分、ユーザーがオンラインにいる時間と消費したトラフィックの量を調べるスクリプトを呼び出します。 そして、どちらかが超過した場合、許可ルールが削除され、次のリクエストでこのユーザーは再びスタートページにリダイレクトされます。

それが基本的にこのスキームのポイントです。 そのため、実装を継続します。



次に、ファイアウォールを構成する必要があります。



基本設定のみがあることをすぐに言いたいです。 SSHを使用してマシンを構成する場合、このマシンへのアクセスを許可するルールを追加する必要があります。



許可ルールは200〜600であるため、転送ルールは番号1000になります。



/etc/firewall.sh



ipfw -q flush



ipfw pipe 1 config bw 512Kbit/s mask dst-ip 0x00000001 #

ipfw pipe 2 config bw 256Kbit/s mask dst-ip 0x00000001 #



ipfw nat 1 config log if re0 reset same_ports # , .



ipfw add 120 nat 1 ip from 10.128.1.0/24 to any via re0 #

ipfw add 121 nat 1 ip from any to 192.168.24.154 via re0 # .



ipfw add 1000 fwd 10.128.1.1,80 tcp from any to any 80 via re1 # , .









絶対にすべてのリクエストが認証ページに到達するためには、次の内容でサイトのディレクトリのルートに「 .htaccess 」ファイルを作成する必要があります(httpd.confでRewriteを許可した後)。



RewriteEngine on

ErrorDocument 404 10.128.1.1/index.php







次に、アドレスバーにサイト(http://habrahabr.ru)だけでなく特定のページ(http://habrahabr.ru/i/habr.gif)が含まれている場合でも、目的のページが開きます。



現在は、現在のセッションに関するデータを格納するデータベースにテーブルを作成し、DHCPサーバーを構成し、すべての主要な作業を行う必要なPHPスクリプトを作成するだけです。



MySQLテーブルは完全にシンプルです。 ルール番号、セッション開始時間。



 CREATE TABLE `hotspot` ( `time_begin` timestamp NOT NULL default '0000-00-00 00:00:00', `rule_num` smallint(5) unsigned NOT NULL, KEY `rule_num` (`rule_num`) ) ENGINE=MyISAM DEFAULT CHARSET=cp1251 ;
      
      





さらに、以下で説明するすべてのファイルは、サイトのディレクトリにある必要があります。



config.php設定ページから始めましょう:



 <?php //     : define('conf_DB_HOST', 'localhost'); define('conf_DB_USER', 'root'); define('conf_DB_PASS', ''); define('conf_DB_NAME', 'hotspot'); define('RULE_NUM_MIN', 200); //,     ,  . define('CLIENTS_TIME', '1800'); //   30  ( ) define('CLIENTS_TRAF', '30'); //    //,        define('RULE_ADD_IP', '/usr/local/bin/sudo /sbin/ipfw add %s pipe 1 ip from any to %s'); define('RULE_ADD_IP2', '/usr/local/bin/sudo /sbin/ipfw add %s pipe 2 ip from %s to any'); define('RULE_DEL_IP', '/usr/local/bin/sudo /sbin/ipfw delete %s'); define('RULE_DEL_IP2', '/usr/local/bin/sudo /sbin/ipfw delete %s'); //   . $db_link = mysql_connect(conf_DB_HOST, conf_DB_USER, conf_DB_PASS); if (!$db_link) echo('Connect Error!'); if (!mysql_select_db(conf_DB_NAME, $db_link)) echo('Connect Error'); ?>
      
      







次に、ユーザーがリダイレクトされるメインページはindex.phpです。

 <H1>   Wi-Fi !<br>    30   30  . </H1> <?php $redir='http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; echo('<form method=GET action="open.php">'); echo("<input type=hidden name=redir value=$redir>"); echo('<input value=" !" type="submit"></form>'); ?>
      
      







このページは、最初に入力されたアドレスを判別し、次にリダイレクトされます。 これは、ファイアウォールルールを追加するだけでなく、 open.phpスクリプトを実行します。

 <?php require_once('config.php'); $user_ip = $_SERVER['REMOTE_ADDR']; $current_date = time(); //       .      200.    RULE_NUM_MIN. $temp = 0; $sql = 'SELECT rule_num FROM hotspot ORDER BY rule_num'; $res = mysql_query($sql); if ($res) { $t = mysql_fetch_array($res); if (!$t) $rule_num = RULE_NUM_MIN; else { while ($temp = mysql_fetch_array($res)) { if (($t[0]+1) < $temp[0]) break; $t = $temp; } $rule_num = $t[0]+1 } } else return false; //     2 .  - " ",  " ".      200  .      200 . $command = sprintf(RULE_ADD_IP, $rule_num, $user_ip); exec($command); $command2 = sprintf(RULE_ADD_IP2, $rule_num+200, $user_ip); exec($command2); //        . $sql = 'INSERT INTO hotspot (time_begin, rule_num) values (NOW(),'.$rule_num.')'; mysql_query($sql); //    ,     . $redir=$_GET['redir']; header("Location: $redir"); return true; ?>
      
      







これらの操作後、ユーザーはインターネットに完全にアクセスできます。 ファイアウォールは何もブロックしないため、ICQ、エージェント、その他すべてがこれで機能します。 しかし一方で、これもおそらく正しくないため、ファイアウォールを構成し、必要なポートのみを残す必要があります。 しかし、これはすでに必要に応じています。



制限の1つを超えた場合にのみユーザーを切断するようになりました。それだけです。

当初はtrafdを使用して交通量をカウントすることを計画していましたが、判明したように、大砲からスズメを撃つよりも、交通量がすでに考慮しているものを使用する方が適切です。 つまり、IPFW。 ipfw showが呼び出されると、3番目の列にファイアウォールを通過したバイト数が含まれます。 また、ユーザーごとに個別のルールがあるため、ルール番号によって、このユーザーがトラフィックを使用した量を簡単に計算できます。

cron.phpスクリプトがこれを行います

 <?php require_once('config.php'); //     ,      ,            . $sql = 'SELECT * FROM hotspot WHERE time_begin > 0 AND (TIME_TO_SEC(TIMEDIFF(NOW(), time_begin)) > '.CLIENTS_TIME.')'; $res = mysql_query($sql); if ($res) { while ($user = mysql_fetch_assoc($res)) { block($user['rule_num']); } } //    IPFW        .     - . $sql = 'SELECT * FROM hotspot WHERE 1'; $res = mysql_query($sql); if ($res) { while ($user = mysql_fetch_array($res)) { $rule=$user['rule_num']; exec("/usr/local/bin/sudo /sbin/ipfw show $rule | awk '{print($3)}'",$ct); if($ct[0]>=CLIENTS_TRAF*1024*1024) block($rule); } } return true; //,         . function block($num) { $command = sprintf(RULE_DEL_IP, $num); exec($command); $command2 = sprintf(RULE_DEL_IP2, $num+200); exec($command2); $sql = 'DELETE FROM hotspot WHERE rule_num='.$num; mysql_query($sql); } ?>
      
      







ここで、crontabに飲み物を追加し、1分ごとにスクリプトが制限を超えているかどうかを確認します。

*/1 * * * * /usr/local/bin/php /var/www/data/cron.php







それがすべてのようです。

当然、パス、ネットワークカードの名前、およびいくつかの小さなものは異なる場合がありますが、



PS DHCPをほとんど忘れていました。 設定は次のとおりです。

# .

option domain-name "hotspot.my";

# . .

option domain-name-servers 8.8.8.8;



# . .

default-lease-time 600;

max-lease-time 7200;



# . .

subnet 10.128.1.0 netmask 255.255.255.0 {

range 10.128.1.20 10.128.1.220;

option routers 10.128.1.1;

}









今ではすべてが見えます。



All Articles