web-dev-qa-db-ja.com

Androidのキャプティブポータルの検出によってブラウザーウィンドウがトリガーされないのはなぜですか?

Nginxを使用して簡単なウェブサイトをホストしているRaspberry Piを持っています。 RPiはワイヤレスアクセスポイントとして機能しています。ユーザーはワイヤレスネットワークに接続でき、RPiはIP(DHCPサーバーを実行)を提供し、サイトにアクセスできます。

RPiは実際にはユーザーにインターネットを提供しないため(この1つのサイトのみ)、ユーザーがサイトを見つけやすくしました。サイトの正確なURLを知る代わりに、DHCPサーバーがクライアントに使用するように指示するdnsサーバー(dnsmasq)に、すべてのクエリをRPiのLAN IP(192.168.30.1)に解決するように指示しました。

この時点で、私のnginxのconfigには次のようなエントリがあります。

  • ユーザーのリクエストのHostフィールドがMyRPiServer.comでない場合、302リダイレクトをMyRPiServer.comに送信します。
  • ホストがMyRPiServer.comの場合、ローカルWebサイトを提供します

これは素晴らしい作品です。

もう一歩踏み出したかった。 Androidがワイヤレスネットワークに接続すると、 http://connectivitycheck.gstatic.com/generate_204 (または他の同様のGoogleページの1つ)に接続しようとします)具体的には、リクエストがリダイレクトされているかどうかを確認します。204コードを取得した場合、すべてが正常であると想定します。そうでない場合は、キャプティブポータルの背後にあると想定し、キャプティブポータルログインを開くブラウザウィンドウをポップアップします。

何らかの理由で、私がnginxに、302リダイレクトまたは200(何らかのテキストを含む)のいずれかでgenerate_204ページのリクエストに応答するように指示すると、Androidはブラウザーをポップアップしません。

私は組み込みのホットスポット機能を備えたmikrotikルーターを使用していますが、実際にはAndroidがブラウザをキャプティブポータルログインでポップアップします(同じテスト電話上)。トラフィックを見ると私のクライアントを送信します。これは単純なHTTP 200で、私のようにテキストが含まれています。

機能しているように見える1つのことは、DNSサーバーがすべてを192.168.30.1に解決することを無効にし、iptablesを使用してポート80をRPiのlocalhostにリダイレクトすることです。

Androidのキャプティブポータルの検出に関してポート80のリダイレクトが機能するが、すべてをRPiローカルIPに解決するようにDNSサーバーを構成できない理由を誰かが知っていますか?

ここにあるコードを見ると https://stackoverflow.com/a/14030276/4258196 、Androidが気にするのは接続できるかどうかだけですホストに接続し、HTTP 204が返された場合私の場合、接続は確実で、204は返されません(nginxログは、HTTP 302およびHTTP 200を送信していることを示しています)。

私の電話はAndroid= 8を実行しているので、リンクされたコードは今私が想定しているものと異なるかもしれません。

5
Tal

私が見つけた解決策は、すべてを192.168.30.1に解決し続けるようにdnsmasqを設定することですが、キャプティブポータルテストサーバーにはいくつかの例外があります。

10.45.12.1 clients3.google.com
10.45.12.1 clients.l.google.com
10.45.12.1 connectivitycheck.Android.com
10.45.12.1 connectivitycheck.gstatic.com
10.45.12.1 play.googleapis.com

基本的に、DNSサーバーを使用して上記のドメインを解決しようとすると、10.45.12.1の応答が返されます。

10.45.12.1は、何にも属さないランダムなIPです。 192.168.30.1でなくてもかまいません。

ドメインのリストは here からのものです。

これを配置すると、RPiのWiFiに接続するとすぐに、ブラウザーのページがポップアップして私のサイトが表示されます。

これは解決策ですが、なぜこれが起こるのかという質問に対する答えではありません。どなたかご説明頂ければ幸いです。

編集:

このソリューションでは、デバイスのWiFiに数回接続および切断すると、Androidがログインページをポップアップ表示する場合とそうでない場合があります。同様のことをしている人は、最後に、より良い解決策として、私はこれを行いました:

  • DNSmasqですべてを10.45.12.1(または192.168.30.0/24サブネット外のもの)に解決します
    • 192.168.30.0/24サブネット(またはLANサブネットが何であれ)の外になければなりません。そうでない場合、クライアントはARPを使用して特定のデバイスのMACアドレスを見つけようとしますが、デバイスは実際には失敗しません。存在する
  • Iptablesに、wifiインターフェースからlocalhostに送信されるポート80を転送させる

これは、Android、OS X、およびWindowsで機能します。これをテストするiOSデバイスがありません。 this によると、iOSデバイスには追加の作業が必要になる場合があります。

なぜこれが必要なのか、なぜすべてを192.168.30.1に解決してもそもそもうまくいかないのか、私はまだ興味があります。

3
Tal

私はこれを理解するために多くの時間を費やし、ついにそれを行いました。あなたはここでコードを見ることができます https://github.com/tretos53/Captive-Portal

これは、パブリックIP、iptables、nginxリダイレクトを指すドメインの組み合わせです。

0
tr53

これにはさまざまな理由があり、特定のハードウェア電話メーカーも考えられます。私は現在、デバイスIPを使用してすべてのDNSクエリに応答するMongoose OS用のキャプティブポータルライブラリを構築しており、Samsungデバイス以外のデバイスで、テキスト付きの200応答を必要とするような問題はありません。

これがライブラリスタックです: https://github.com/tripflex/captive-portal-wifi-stack

具体的には、私が使用するエンドポイントの詳細、およびREADMEでの処理方法の詳細とともに、キャプティブポータルの処理を以下に示します。

https://github.com/tripflex/captive-portal

Samsungデバイスで使用した1つのソリューションは、メタリフレッシュタグを使用して生成されたHTMLファイルを含む200を返すことです。

https://github.com/tripflex/captive-portal#cportalredirect_file-setting

<html>
   <head>
      <title>Redirecting to Captive Portal</title>
      <meta http-equiv='refresh' content='0; url=PORTAL_URL'>
   </head>
   <body>
      <p>Please wait, refreshing.  If page does not refresh, click <a href='PORTAL_URL'>here</a> to login.</p>
   </body>
</html>

しかし、実際の主なことは、特定のデバイスごとにエンドポイント処理を設定することでした。

https://github.com/tripflex/captive-portal#known-endpoints

  • /mobile/status.php Android 8.0(Samsung s9 +)
  • /generate_204 Android
  • /gen_204 Android
  • /ncsi.txt ウィンドウズ
  • /hotspot-detect.html iOS/OSX
  • /hotspotdetect.html iOS/OSX
  • /library/test/success.html iOS
  • /success.txt OSX
  • /Kindle-wifi/wifiredirect.html com.Android.captiveportalloginでリクエストされた場合のKindle
  • /Kindle-wifi/wifistub.htmlキャプティブポータルのログインウィンドウでリクエストする前のKindle(おそらく検出用?)
0
sMyles