1年ほど前に、私のリーダーシップは、組織の領土の訪問者に無料のWi-Fiネットワークを展開することにしました。 1つの興味深い条件がなければ、すべてがシンプルで平凡なものになります。ユーザーがインターネットにアクセスする前に、「広告」のある情報ページを見なければなりません。
少し分析した結果、これは、おそらくLinux上で、別のゲートウェイサーバーを使用しないと達成できないという結論に達しました。 少なくとも同様のソリューションの開発/実装に関与する企業に送信されたタスクの一般的な説明を含む短いToRは、外部ソリューションを注文すると、プロジェクトコストが急騰することを示しました。
トピックに関する多くの審議と空想の後:これを実装する方法(プロトコルの深みに没頭し、パッケージ、ヘッダーなどを置き換える数十のエロティックな空想を含む)、シンプルで論理的なソリューションが見つかりました。
素晴らしい-ただ
操作の簡単な原則:
- ネットワークに接続するユーザーは、通常のdhcpサーバーを使用してIPアドレスを受け取ります。 設定では、サーバーがデフォルトゲートウェイとして指定されています。
- デフォルトのiptablesルールセットはサーバーに登録されています:
[root@wifi ~]# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
REDIRECT tcp -- anywhere !192.168.143.1
DROP udp -- anywhere !192.168.143.1 udp dpt:!domain
このため、ユーザーからのすべての要求(DNSパケットを除く)はローカルサーバーにリダイレクトされます。 - ユーザーが最初にWebページを読み込もうとすると、ローカルのnginxサーバーにアクセスして、行を含むhtmlページが表示されます。
<?php
$run = "ts /usr/share/nginx/html/script.sh {$_SERVER['REMOTE_ADDR']}";
exec($run);
?>
- そして、ここから楽しみが始まります! このページは、サーバー上にあるスクリプトを起動します(開始パラメーターとしてクライアントのIPアドレスを渡します)。
#!/bin/sh
LOG_FILE=/var/log/script_log
{
date | tr "\n" " "
echo -n '|IP:'
echo -n $1
echo -n '|MAC:'
/sbin/arp $1 -n | grep $1 | tr -s ' ' | cut -d ' ' -f 3 | tr "\n" " "
mac=`/sbin/arp $1 -n | grep $1 | tr -s ' ' | cut -d ' ' -f 3 | tr "\n" " "`
if ( sudo /sbin/iptables -n -L -t nat --line-numbers | grep $1 > /dev/null )
then
echo '|Rule exists!!'
else
echo -n '|Add rule '
sudo /sbin/iptables -t nat --insert PREROUTING -s $1 -j ACCEPT
echo -n '|Creat shedule:'
echo "sudo /sbin/iptables -t nat -D PREROUTING -s $1 -j ACCEPT " | at -m now + 45 minutes
sudo /usr/bin/python /usr/share/nginx/html/stat.py ${mac}
fi
} >> $LOG_FILE 2>&1
主に2つのアクションを実行します。iptablesにルールを追加し、atに保留中のタスクを作成します。
ルール:
sudo /sbin/iptables -t nat --insert PREROUTING -s $1 -j ACCEPT
PREROUTINGチェーンの最初の位置に配置されるため、リダイレクトルールの前に配置されます。 その結果、このアドレスを持つユーザーはインターネットへのフルアクセスを取得します。
2番目のメインアクション、ルールの作成場所:
echo "sudo /sbin/iptables -t nat -D PREROUTING -s $1 -j ACCEPT " | at -m now + 45
実際、ユーザーのセッションは45分に制限されます。その後、ルールは削除され、ユーザーは再度リダイレクトされます。
回路は実装され、テストされ、実行可能であることが証明されました。
これはおそらく物語を終える価値があるでしょうが、「1年未満」では、プロジェクトを完成させ、小さな妨害を排除し、非常にオリジナルの機能を追加する作業が行われました。
メンタリティ
最初に発生した問題は「虐待者」でした。 特に景品が渇いている人の中には、ネットワークを非常に長い間使用している人がいることがわかりました。 そのようなことを識別するために、統計を保持することが決定されました。 主な問題は、すべての課金システム(または統計を実行するための単純なモジュール)がログインまたはIPアドレスのいずれかを基本要素として考慮することです。 私たちの場合、最初のものは単にそこにはありませんが、2番目のものに接続することはできません。 IPアドレスは静的ではありません。 必要な統計は、MACアドレスに基づいていました。 多くの研究の結果、適切なソリューションは見つかりませんでした。 したがって、独自の
import sys
file = open('/var/log/stat.file','r')
line = file.readlines()
line2 = ''
i = 0
while len(line) > i :
line2 = str(line[i])
line2 = line2.rstrip()
line2 = line2.split()
if line2[0] == str(sys.argv[1]) :
line2[1] = str(int(line2[1])+1 )
del line[i]
line.insert(i,line2[0]+' '+line2[1]+'\n')
break
i = i + 1
else :
line.append(str(sys.argv[1])+' '+'1'+'\n')
###########
file.close()
file = open('/var/log/stat.file','w')
file.writelines(line)
file.close()
これはメインスクリプトから呼び出されました。 logrotateに、このファイルの1週間のセクションが追加されました。 また、2週間以内に、サーバーの前に設置されたスイッチでMACアドレスがブラックリストに登録された「通常の顧客」のリストが届きます。
自転車は機能しません!
次の問題はより独創的でした。複数のスクリプトを同時に実行すると、そのうちの1つが実行されずにiptablesエラー(「iptables:Unknown error 4294967295」シリーズの何か)をスローしました。 それがルールを作成するためのスクリプトである場合、ひどいことは何も起こりませんでした-ユーザーは単にページを更新し、再起動されたスクリプトはエラーなしで動作しました同時に実行するようになりました)。
このようなエラーで、ルールを削除するタスクがクラッシュした場合、IPアドレスはリストに残り、ユーザーは無制限にインターネットを無限にサーフィンできます。
最初の回避策は、iptablesおよびatタスクプール内のアドレスのリストに一致する単純なbashスクリプトの形式で提供されました。
#!/bin/bash
LOG_FILE=/var/log/script_log
{
echo -n "Checking rules: "
date | tr "\n" " "
ar_ip=(`sudo iptables -L -t nat -n | grep ACCEPT | grep -v policy | cut -d ' ' -f 10 | tr '\n' ' '`)
ar_at=(`grep 168.143. /var/spool/at/* | cut -d ' ' -f 9 | tr '\n' ' '`)
count=${#ar_ip[@]}
for ((i=0; i <= count ; i++ ))
do
for h in "${ar_at[@]}"
do
if [[ ${ar_ip[$i]} == $h ]]
then
unset ar_ip[$i]
continue 2
fi
done
done
echo -n "|Delete rules: "
for i in ${!ar_ip[*]}
do
sudo /sbin/iptables -t nat -D PREROUTING -s ${ar_ip[$i]} -j ACCEPT
echo -n ${ar_ip[$i]} " "
done
echo "|Checking done"
} >> $LOG_FILE 2>&1
スクリプトは/etc/cron.hourlyに配置され、iptablesエラーの結果を正しく削除しました。原則として、解決策は十分でしたが、「完璧に制限はありません」と私はより良い解決策を求めて無限の広がりを耕し始めました。 そしてそれが見つかりました。 「居心地の良い」Linuxフォーラムの1つで、マストドンの1人が私にこのプロジェクトを教えてくれました
実際、このプロジェクトは、bashスクリプトを実行してプールに配置し、それらを次々に厳密な順序で実行するための小さな開発です。
Webページのスクリプト起動行は、見た目が変更されています。
ts /usr/share/nginx/html/script.sh {$_SERVER['REMOTE_ADDR']}
そして、iptablesエラーが消えました。
3番目の問題、または私がオープンソースコミュニティをどのように助けたか
プロジェクトがすでに約半年間働いていて、人々がすでにそれについて十分に学んでいたとき、別の深刻な問題が現れました:アクセスポイント(Lynksys wap54g)が自発的に切断/ハング/再起動し始めました。 当然、最初に頭に浮かんだのは、ログを調べることでした。 判明したように、主婦はログを読む必要がないため、Lynksysは「ホーム」セグメントに起因する無駄ではありません。 ログに含まれるのは、どのMACアドレスが接続されているかだけです。 さらに、ログ形式は一意であり、通常のsyslogサーバーはそれを理解しませんでした。 いつものように、Lynksysは、名前に魔法のようなものを含む、何らかの疑わしいユーティリティを提供しました。おそらく、ホームネットワークを独立して即座に設定できると思われます。 ユーティリティの簡単な研究の後、それは不適切であると結論付けられ、再び広大な広がりの中で長い旅が始まりました。
彼らは早く幸せだったことが判明した。 ログエントリは次のようになりました。
May 20 12:04:42 /usr/local/bin/wap54g-log[17544] Wireless PC connected 00:26:C7:61:BB:26
また、クライアントが接続しているポイントを理解することは不可能でした。 したがって、ポイントの不適切な動作の最も可能性のある理由の1つとして、負荷について結論を出すことです。
そして、私はSを思い出さなければなりませんでした。判明したように、思い出すのではなく、もう一度勉強しなければなりませんでした。 Visual Studioの研究所で2年目に書かれたものは、この小さなユーティリティのコードにリモートでしか似ていませんでした
思慮深く読んだ後、それらのaddr構造体が発見されました。これはsockaddr _in型(unixの標準ソケット型)で、in_addr_t型の単一変数s_addrを含む別のin_addr構造体が含まれています。 「アヒルの卵、うさぎのアヒル、ショックのうさぎ」©。 最もおかしいのは、「in_addr_tのような変数だけでなく、そのような構造が使用されているという事実が歴史的に発展した」というコメントでした。
さらに深くなると、ライブラリ<arpa / inet.h>(Oh my God!arpaの幽霊!)がこれらの構造を操作するための機能を含んでいることが発見されました。 inet_ntoa(strcu)関数を変換し、これをすべてユーティリティの出力に入れると、次のような結果になりました。
May 20 12:23:38 192.168.143.114 /usr/local/bin/wap54g-log[17544] Wireless PC connected 00:26:C7:61:BB:26
主な違いは、ポイントアドレスの可用性です。 つまり これで、ロードポイントの分布を判断できます。
直観/論理/ 5番目のポイントが判明したので、私は失望しませんでした。 そして、小さな観察の後、Wap54gは30人の同時接続ユーザーにも耐えられないことが判明しました。
この問題はまだ解決されていません。 これまでのところ、ポイントをより「工業的な」ものに置き換える以外の選択肢はありません。 経営陣が何をすべきかを決定し、ユーティリティの開発者に感謝状と修正の提案が送られました。
さらに小さな問題もありました。リダイレクトが発生したアドレスにページの名前とアドレス行にgetリクエストが含まれていた場合、nginxは404ページを返しました。 仮想サーバーの構成「rewrite ^ /(。*)/Index.php last;」の1行で決定されました。 しかし、ここではそのような些細なことについて話すべきではありません。 それらはすべて平凡で日常的なものです。
結論の代わりに
この記事を書く最終決定は、「システム管理者になる方法-初心者向けガイド」という記事をいくつか読んだ後に承認されました。 私は自分がどんな教祖であるとは考えていません。私はLinux指向のミドルハンドのシステム管理者であることを心から理解しています。 この記事では、日常業務に必要な知識のほんの一部しか示していません。 ちょうどhtml、bash、python、およびCの少しの知識です。まあ、必須のベースとして:理論(ITの、ネットワークからプログラミングまで)の知識、および基本的に作業しなければならないOS(ユーティリティ、システムアプリケーション)の知識。 これは良い追加になると思います。