저는 nginx를 사용하여 간단한 웹사이트를 호스팅하는 Raspberry Pi를 가지고 있습니다. RPi는 무선 액세스 포인트 역할을 합니다. 사용자는 무선 네트워크에 연결할 수 있고 RPi는 IP(DHCP 서버 실행)를 제공한 다음 사이트에 액세스할 수 있습니다.
RPi는 실제로 사용자에게 인터넷을 제공하지 않기 때문에(이 사이트 하나만) 사용자가 사이트를 더 쉽게 찾을 수 있도록 만들었습니다. 사이트의 정확한 URL은 모르지만 대신 내 RPi(192.168.30.1)의 LAN IP에 대한 모든 쿼리를 해결하기 위해 사용할 DNS 서버(dnsmasq)를 클라이언트에게 알려주도록 DHCP 서버에 지시합니다.
이 시점에서 nginx 구성에 다음 항목이 있습니다.
- 사용자가 요청한 호스트 필드가 MyRPiServer.com이 아닌 경우 302 리디렉션이 MyRPiServer.com으로 전송됩니다.
- 호스트가 MyRPiServer.com인 경우 로컬 웹사이트를 제공합니다.
이것은 훌륭하게 작동합니다.
나는 한 단계 더 나아가고 싶다. Android가 무선 네트워크에 연결되면 다음 장치에 연결을 시도합니다.http://connectivitycheck.gstatic.com/generate_204(또는 다른 유사한 Google 페이지 중 하나) 요청이 리디렉션되고 있는지 구체적으로 확인하세요. 204 코드를 받으면 모든 것이 정상이라고 가정하십시오. 그렇지 않은 경우 종속 포털 뒤에 있는 것으로 간주되며 종속 포털 로그인을 여는 브라우저 창이 팝업됩니다.
어떤 이유로 nginx에게 302 리디렉션 또는 200(일부 텍스트 포함)을 사용하여 generate_204 페이지에 대한 요청에 응답하도록 지시할 때 Android는 브라우저를 팝업하지 않습니다.
나는 핫스팟 기능이 내장된 mikrotik 라우터를 가지고 있으며 안드로이드가 브라우저를 팝업하고 동일한 테스트 전화에서 캡티브 포털을 사용하여 로그인할 수 있게 해줍니다. 내 클라이언트로 보내는 트래픽을 보면 나와 같은 텍스트가 포함된 간단한 HTTP 200입니다.
작동하는 것으로 보이는 한 가지 방법은 DNS 서버를 비활성화하여 모든 것을 192.168.30.1로 확인하고 iptables를 사용하여 포트 80을 RPi의 localhost로 리디렉션하는 것입니다.
Android의 Captive Portal 감지에서 포트 80을 리디렉션하면 작동하지만 모든 것을 RPi 로컬 IP로 확인하도록 DNS 서버를 구성하면 작동하지 않는 이유를 아는 사람이 있습니까?
여기에서 찾은 코드를 확인하세요.https://stackoverflow.com/a/14030276/4258196, Android가 관심을 갖는 유일한 것은 호스트에 연결할 수 있는지 여부와 HTTP 204를 반환하는지 여부인 것 같습니다. 내 경우에는 확실히 연결되어 있고 확실히 204 백을 수신하지 않습니다(nginx 로그에 HTTP 302 및 HTTP 200을 보내는 것으로 표시됨).
내 휴대폰은 Android 8을 실행하고 있으므로 연결된 코드가 지금은 다를 수 있다고 생각합니다.
답변1
내가 찾은 해결책은 캡티브 포털 테스트 서버에 대한 몇 가지 예외를 제외하고 모든 것을 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일 필요는 없습니다.
다음의 도메인 목록여기.
이 작업을 완료하면 RPi의 WiFi에 연결될 때마다 내 사이트를 표시하는 브라우저 페이지가 팝업됩니다.
이것은 해결책이지만 실제로 왜 이런 일이 발생하는지 대답하지 않습니다. 누구든지 설명해 주시면 매우 감사하겠습니다.
편집하다:
이 솔루션을 사용하면 장치의 WiFi에 여러 번 연결하고 연결을 끊으면 Android에서 로그인 페이지가 팝업되는 경우도 있고 그렇지 않은 경우도 있습니다. 비슷한 일을 하는 사람이라면 결국 더 나은 솔루션을 위해 다음과 같이 결정했습니다.
- DNSmasq가 모든 것을 10.45.12.1(또는 192.168.30.0/24 서브넷 외부의 모든 것)로 확인하도록 합니다.
- 192.168.30.0/24 서브넷(또는 모든 LAN 서브넷) 외부에 있어야 합니다. 그렇지 않으면 클라이언트는 ARP를 사용하여 지정된 장치의 MAC 주소를 찾으려고 시도하며 장치가 실제로 존재하지 않기 때문에 실패합니다.
- iptables가 Wi-Fi 인터페이스에서 localhost로 포트 80을 전달하도록 허용
이는 Android, OS X 및 Windows에서 작동합니다. 이것을 테스트할 iOS 장치가 없습니다. ~에 따르면이것, iOS 장치에는 몇 가지 추가 작업이 필요할 수 있습니다.
이것이 왜 필요한지, 192.168.30.1에 대한 모든 것을 해결하는 것이 처음에는 작동하지 않은 이유가 여전히 궁금합니다.
답변2
나는 이것을 알아 내려고 많은 시간을 보냈고 마침내 해냈습니다. 여기서 코드를 볼 수 있습니다https://github.com/tretos53/Captive-Portal
이는 공인 IP를 가리키는 도메인, iptables 및 nginx 리디렉션의 조합입니다.
답변3
여기에는 여러 가지 이유가 있으며 특정 하드웨어 휴대폰 제조업체로 인해 발생할 수도 있습니다. 현재 장치 IP를 사용하여 모든 DNS 쿼리에 응답하기 위해 Mongoose OS용으로 구축된 Captive Portal 라이브러리가 있으며 200 텍스트 응답이 필요한 것으로 보이는 Samsung 장치 이외의 장치에는 문제가 없습니다.
라이브러리 스택은 다음과 같습니다. https://github.com/tripflex/captive-portal-wifi-stack
특히, 제가 사용한 엔드포인트에 대한 세부 정보와 추가 정보에서 이를 처리하는 방법에 대한 세부 정보와 함께 종속 포털 처리는 다음과 같습니다.
https://github.com/tripflex/captive-portal
제가 삼성 장치에 사용하는 솔루션 중 하나는 결과 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
안드로이드 8.0(삼성 s9+)/generate_204
기계적 인조 인간/gen_204
기계적 인조 인간/ncsi.txt
윈도우/hotspot-detect.html
iOS/OSX/hotspotdetect.html
iOS/OSX/library/test/success.html
iOS 시스템/success.txt
OSX/kindle-wifi/wifiredirect.html
요청 시 Kindle용 com.android.captiveportallogin을 사용하세요./kindle-wifi/wifistub.html
캡티브 포털 로그인 창을 요청하기 전에 Kindle을 사용하세요(탐지를 위해?)