Nginxを使用して簡単なウェブサイトをホストしているRaspberry Piを持っています。 RPiはワイヤレスアクセスポイントとして機能しています。ユーザーはワイヤレスネットワークに接続でき、RPiはIP(DHCPサーバーを実行)を提供し、サイトにアクセスできます。
RPiは実際にはユーザーにインターネットを提供しないため(この1つのサイトのみ)、ユーザーがサイトを見つけやすくしました。サイトの正確なURLを知る代わりに、DHCPサーバーがクライアントに使用するように指示するdnsサーバー(dnsmasq)に、すべてのクエリをRPiのLAN IP(192.168.30.1)に解決するように指示しました。
この時点で、私のnginxのconfigには次のようなエントリがあります。
これは素晴らしい作品です。
もう一歩踏み出したかった。 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を実行しているので、リンクされたコードは今私が想定しているものと異なるかもしれません。
私が見つけた解決策は、すべてを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がログインページをポップアップ表示する場合とそうでない場合があります。同様のことをしている人は、最後に、より良い解決策として、私はこれを行いました:
これは、Android、OS X、およびWindowsで機能します。これをテストするiOSデバイスがありません。 this によると、iOSデバイスには追加の作業が必要になる場合があります。
なぜこれが必要なのか、なぜすべてを192.168.30.1に解決してもそもそもうまくいかないのか、私はまだ興味があります。
私はこれを理解するために多くの時間を費やし、ついにそれを行いました。あなたはここでコードを見ることができます https://github.com/tretos53/Captive-Portal
これは、パブリックIP、iptables、nginxリダイレクトを指すドメインの組み合わせです。
これにはさまざまな理由があり、特定のハードウェア電話メーカーも考えられます。私は現在、デバイス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(おそらく検出用?)