0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【目次】【Apache + PHP + SQLite3】webページへのアクセス頻度をISP単位で制限してみる

Last updated at Posted at 2025-10-08

この一連の記事は書きかけです。
今後、更新を中止する可能性もありますのでご了承ください。

次回:


1. やりたいこと

Apache 2.4 以降で稼働しているwebページへのアクセスを "ISP単位で" 集計し、
極端な高頻度でアクセスがある ISP からのアクセスがあった場合は、一定期間 429 Too Many Requests を返すようにしたい。
ISPの同一性判定にはAS番号を用いる。

1-1. 実験環境

  • OS: Rocky Linux 9
  • http(s)サーバ: Apache/2.4.62
    • サーバ設定ファイル (通称httpd.conf) のパス: /etc/httpd/conf/httpd.conf
    • (ユーザ:グループ): apache:apache
    • ドキュメントルート: /var/www/html
  • php: PHP 8.0.30 (cli)
    • パス: /usr/bin/php
  • SQLite3(phpに同梱されているもの): version 3.34.1
  • その他インストールしたもの
    • nano エディタ: version 5.6.1

1-2. ISPと「AS番号」とは

インターネットサービスプロバイダ。
「プロバイダに開示請求」と言った文脈でも出てくるプロバイダのことで、ネット利用者をインターネットに繋げる事業者。
日本国内の例で言えば、ドコモ、So-net、KDDI、NUROなど。

ISPは、ネット利用者とインターネットの架け橋であると同時に、「インターネットを構成するネットワークの単位」の一種でもある。「インターネットを構成するネットワークの単位」のことをAS (自律システム) という。

平たく言えば、AS同士の相互通信によって、

ネット利用者A
<-> Aさんの利用するISP(AS) // ここから インターネット
<-> 他のAS1
<-> ...(全部AS)... 
<-> Bさんの利用するISP(AS)  // ここまで インターネット
<-> ネット利用者B

というように繋がっている。

ASにはそれぞれ固有の「AS番号」が振られている。

なので、AS番号を特定できれば、それがそのままISPの識別が出来たということになる。 →厳密には違うので、気になる人は「蛇足」を読んでください。

蛇足

本当は、ISPとAS番号は一対一対応にはなっていない。
なので厳密にISP単位でのアクセス制限をしたいのであれば、別の方法を検討する必要がある。

「一つのISPが複数のAS番号を持つ場合」も、逆に「複数のISPが共通のAS番号を持つ場合」もある。

例えば、大企業が地域や国ごとにAS番号を分けている場合や、
B社がA社に吸収合併されて一つのISPになったにも関わらず、AのAS番号とBのAS番号を両方使い続ける場合などは、
「一つのISPが複数のAS番号を持つ場合」に相当する。

また、複数の子会社ISPが、親会社の一つのAS番号を共用している場合は、
「複数のISPが共通のAS番号を持つ場合」に相当する。

(蛇足 ここまで)

2. 手順

次の手順で、今回のやりたいこと

極端な高頻度でアクセスがある (AS番号) からのアクセスがあった場合は、一定期間 429 Too Many Requests を返す

を実現する。

  1. Apache で、リクエストごとにphpを実行できるようにする
  2. Apache と phpプログラムで、リクエストごとに ipアドレスを記録できるようにする
  3. Apache と phpプログラムで、アクセス可否を判定できるようにする (仮)
  4. phpプログラムで、ipアドレスから AS番号を求め、AS番号からipアドレス範囲を求める
  5. Apache と phpプログラムで、アクセス可否を判定できるようにする (本番)
  6. 429 Too Many Requests ページをカスタマイズする

2-1. 手順1の目的

まず、「アクセスの多いAS番号だけ 429 Too Many Requests に転送する」という機能は Apacheには無い。
そこで、リクエストごとにApache から phpプログラムを呼んで、phpプログラムのほうで何とかしたい。
そのためにまずは「リクエストごとに phpを実行する」を実現するのが手順1である。

2-2. 手順2~3の目的

手順1で Apache と phpプログラムを連携させる際に、

  • Apache が phpプログラムに ipアドレスを渡す必要がある
    • (phpプログラムは、 ipアドレス を受け取らない限り、AS番号の求めようがない)
  • Apache は phpプログラムから判定結果を受けとる必要がある
    • (Apacheが判定結果を受け取れなければ、phpプログラムに判定を任せた意味がない)

そのため、ipアドレスの受け渡しを手順2で実現し、
判定結果(ダミー)の受け渡しを手順3で実現する。

手順3で、ダミーの判定結果を受け渡しするのは、判定プログラムをまだ書いていない(手順4以降で書く)からである。

2-4. 手順4の目的

phpプログラムで、「そのAS番号が429 Too Many Requests に転送されるべきであるか」を判定するには、
「ipアドレスからAS番号を特定する」仕組みがそもそも必要である。
これには外部API ipinfo.io を利用するのだが、毎回APIを呼んでいては先方に多大なご迷惑をかけてしまう。
そこで、「AS番号からipアドレス範囲を求める」ことをしてその結果をデータベースに保存しておくことにする。
データベースに情報があれば、APIを呼ばずに済む。
「AS番号からipアドレス範囲を求める」のには、別の外部API RIPEstat を利用する。

このプログラムを書くのが手順4である。

2-5. 手順5~6の目的

(明らかだろう。説明を省略する。)


次回:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?