1. Спасибо большое
OCTAGRAM за развернутый ответ. Комментарии не поддерживают форматирование, поэтому отвечу отдельным постом.
2. У меня получилось как-то проще. Может я что-то упускаю, но работает стабильно на нескольких айфонах с разными версиями IOS (8-10).
Код на python:
# функция обрабатывает URL /hotspot-.*.html
# для запоминания пользователей я использую redis
def get(self):
# если мы помним, что этот пользователь уже обращался на hotspot-.*.html,
# подделываем ответ captive.apple.com
if self.redis_conn.get('apple_wispr:some_user_marker'):
self.finish(
'''
<HTML>
<HEAD><TITLE>Success</TITLE></HEAD>
<BODY>
<a href="http://ya.ru">This link will open in Safari</a>
</BODY>
</HTML>
'''
)
# иначе, запоминаем этого пользователя на 10 секунд
# и отдаем заглушку. всплывет CNA
else:
self.redis_conn.set('apple_wispr:some_user_marker', 1, 10)
self.finish('<html></html>')
Как видно, даже без "success" в body прокатывает.
В nginx это выглядит так:
"GET /hotspot-detect.html HTTP/1.0" 200 13 "-" "CaptiveNetworkSupport-346 wispr"
"GET /hotspot-detect.html HTTP/1.1" 200 273 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_2 like Mac OS X) AppleWebKit/602.3.12 (KHTML, like Gecko) Mobile/14C92"
"GET /hotspot-detect.html HTTP/1.0" 200 273 "-" "CaptiveNetworkSupport-346 wispr"
3. Собственно в чем была моя проблема:
До того, что надо на первый wispr запрос отвечать коряво, а на все остальные подделывать оригинальный ответ captive.apple.com я допер еще до того, как задал этот вопрос.
Проблема была такая: при нажатии на ссылку, от WiFi-сети устройство отключалось и шло в safari через мобильный интернет. Это при том, что в CNA уже была кнопка "Done" и вроде как CNA уже обманут.
Когда до меня дошло, я долго себя материл за тупость. Причина:
Для перенаправления пользователя на сервер авторизации я использую функционал Mikrotik ip hotpsot.
При попытке ios достучаться до captive.apple.com, Mikrotik его редиректил (с помощью HTTP 302) на сервер авторизации. И так при КАЖДОМ ЗАПРОСЕ.
IOS на оригинальные запросы ВСЕГДА получал 302. Интересно, что частично он принимал ответы после редиректа за нормальные (кнопка done же появлялась).
Решение: перенаправить запросы на сервер авторизации без использования HTTP.
Я прописал в DNS Mikrotik'a A-запись captive.apple.com на свой сервер и добавил на сервере обработчик на /hotspot-.*.html
И похоже, что ура.