Captive portal. Настройка переадресации ncsi

Приведу пример настройки переадресации клиентов без денег на captive portal при подключении к сети.

Допустим Nginx установлен, например как я описывал в статье Установка и настройка Nginx. На практике nginx использует меньше ресурсов системы и работает быстрее чем Apache2.

Сделаем файла конфигурации для клиентов у кого закончились деньги:

nano /etc/nginx/sites-enabled/page_credit

Добавим в новый файле следующее:

server {
        allow 10.0.0.0/8;
        allow 172.16.0.0/12;
        deny all;
        server_tokens off;

        listen 81;
        access_log off;

        root /var/www/81;
	index index.php;
        server_name _;

        location / {
            if ( $http_user_agent ~ ^uTorrent ) {
                            return 404;
            }
            if ( $http_user_agent ~ Windows-Update-Agent ) {
                            return 404;
            }
            if ( $http_user_agent ~ "Microsoft NCSI" ) {
                            return 302 https://captive.ixnfo.com;
            }
            if ( $http_user_agent ~ "ESS Update" ) {
                            return 404;
            }
            if ( $http_user_agent ~ "Google Update" ) {
                            return 404;
            }
            if ( $http_user_agent ~ "Microsoft-CryptoAPI" ) {
                            return 404;
            }
            if ( $http_user_agent ~ "Microsoft BITS" ) {
                            return 404;
            }
            if ( $http_user_agent ~ MSDW ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^SeaPort ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^Windows-Media-Player ) {
                            return 404;
            }
            if ( $http_user_agent ~ "Google Update" ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^GoogleEarth ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^Skype ) {
                            return 404;
            }
            if ( $http_user_agent = "MailRuSputnik" ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^Ya\.Online ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^MRA ) {
                            return 404;
            }
            if ( $http_user_agent ~* ^MediaGet ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^BTWebClient ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^Syncer ) {
                            return 404;
            }
            if ( $http_user_agent = "TMUFE" ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^Akamai\ NetSession\ Interface ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^VKSaver ) {
                            return 404;
            }
            if ( $http_user_agent ~ DrWebUpdate ) {
                            return 404;
            }
            if ( $http_user_agent = "" ) {
                            return 404;
            }
            if ( $host ~ geo\.kaspersky\.com ) {
                            return 404;
            }
            if ( $host ~ (su|download|webrep).*\.avast\.com ) {
                            return 404;
            }
            if ( $host = wi2geo.mobile.yandex.net ) {
                            return 404;
            }
            if ( $host ~ bar.*\.yandex\.ru ) {
                            return 404;
            }
            if ( $host ~ (ping|master)\d*\.(dyngate|teamviewer)\.com ) {
                            return 404;
            }
            if ( $host ~ sitecheck\d*\.opera\.com ) {
                            return 404;
            }
            if ( $host ~ (xml\.my|mailsputnik|maps)\.mail\.ru ) {
                            return 404;
            }
            if ( $host = onlineconfigservice.ubi.com ) {
                            return 404;
            }
            if ( $host = com-services.pandonetworks.com ) {
                            return 404;
            }
            if ( $host ~ ticno\.com ) {
                            return 404;
            }
            if ( $host ~ conduit ) {
                            return 404;
            }
            if ( $host ~ cbox\.ws ) {
                            return 404;
            }
            if ( $host ~ (pricelist|metrics)\.skype\.com ) {
                            return 404;
            }
            if ( $host = weather.service.msn.com ) {
                            return 404;
            }
            if ( $host = advstat.letitbit.net ) {
                            return 404;
            }
            if ( $host = skymonk.net ) {
                            return 404;
            }
            if ( $host ~ counter ) {
                            return 404;
            }
            if ( $host ~ pluraserver ) {
                            return 404;
            }
            if ( $host ~ apps.bittorrent.com ) {
                            return 404;
            }
            if ( $host ~ tracker ) {
                            return 404;
            }
            if ( $request_uri ~* (update|feed|announce|rss|xml|json|oauth) ) {
                            return 404;
            }
            if ( $request_uri ~* (toolbar|suggest) ) {
                            return 404;
            }
            if ( $request_filename ~ \.(ico|gif|jpg|png) ) {
                            return 404;
            }
            if ( $request_filename ~ \.(css|xml|js|swf|flv) ) {
                            return 404;
            }
            if ( $request_filename ~ \.(crl|txt|cab|msi|jar) ) {
                            return 404;
            }
            if ( $host ~ norton ) {
                            return 404;
            }
            rewrite ^ https://captive.ixnfo.com/ redirect;
        }
location ~ \.php$ {
                try_files $uri =404;
                include /etc/nginx/fastcgi_params;
                fastcgi_pass unix:/var/run/php5-fpm.sock;
        }
    }

Страничку с текстом я создал на другом сервере, а в файл /var/www/81/index.php я добавил содержимое:

<?php
    header('Content-Type: text/html; charset=cp1251');
    http_response_code(511);
?>
<html>
<head>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="Refresh" content="1;URL=https://captive.ixnfo.com">
</head>
No payment
</html>

Сделаем файла конфигурации для неизвестных клиентов:

nano /etc/nginx/sites-enabled/unknown_clients

Добавим в него:

server {
        allow 10.0.0.0/8;
        allow 10.55.56.0/24;
        deny all;
        server_tokens off;

        listen 82;
        access_log off;
        #access_log /var/log/nginx/unknown.access.log;
        root /var/www/82/;
        index index.php;
        server_name test_ixnfo;
        add_header Cache-Control no-cache;
        #expires 0;

        location / {
            if ( $http_user_agent ~ ^uTorrent ) {
                            return 404;
            }
            if ( $http_user_agent ~ Windows-Update-Agent ) {
                            return 404;
            }
            if ( $http_user_agent ~ "Microsoft NCSI" ) {
                            return 302 http://192.168.2.2:82/index.php;
            }
            if ( $http_user_agent ~ "ESS Update" ) {
                            return 404;
            }
            if ( $http_user_agent ~ "Google Update" ) {
                            return 404;
            }
            if ( $http_user_agent ~ "Microsoft-CryptoAPI" ) {
                            return 404;
            }
            if ( $http_user_agent ~ "Microsoft BITS" ) {
                            return 404;
            }
            if ( $http_user_agent ~ MSDW ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^SeaPort ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^Windows-Media-Player ) {
                            return 404;
            }
            if ( $http_user_agent ~ "Google Update" ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^GoogleEarth ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^Skype ) {
                            return 404;
            }
            if ( $http_user_agent = "MailRuSputnik" ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^Ya\.Online ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^MRA ) {
                            return 404;
            }
            if ( $http_user_agent ~* ^MediaGet ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^BTWebClient ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^Syncer ) {
                            return 404;
            }
            if ( $http_user_agent = "TMUFE" ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^Akamai\ NetSession\ Interface ) {
                            return 404;
            }
            if ( $http_user_agent ~ ^VKSaver ) {
                            return 404;
            }
            if ( $http_user_agent ~ DrWebUpdate ) {
                            return 404;
            }
            if ( $http_user_agent = "" ) {
                            return 404;
            }
            if ( $host ~ geo\.kaspersky\.com ) {
                            return 404;
            }
            if ( $host ~ (su|download|webrep).*\.avast\.com ) {
                            return 404;
            }
            if ( $host = wi2geo.mobile.yandex.net ) {
                            return 404;
            }
            if ( $host ~ bar.*\.yandex\.ru ) {
                            return 404;
            }
            if ( $host ~ (ping|master)\d*\.(dyngate|teamviewer)\.com ) {
                            return 404;
            }
            if ( $host ~ sitecheck\d*\.opera\.com ) {
                            return 404;
            }
            if ( $host ~ (xml\.my|mailsputnik|maps)\.mail\.ru ) {
                            return 404;
            }
            if ( $host = onlineconfigservice.ubi.com ) {
                            return 404;
            }
            if ( $host = com-services.pandonetworks.com ) {
                            return 404;
            }
            if ( $host ~ ticno\.com ) {
                            return 404;
            }
            if ( $host ~ conduit ) {
                            return 404;
            }
            if ( $host ~ cbox\.ws ) {
                            return 404;
            }
            if ( $host ~ (pricelist|metrics)\.skype\.com ) {
                            return 404;
            }
            if ( $host = weather.service.msn.com ) {
                            return 404;
            }
            if ( $host = advstat.letitbit.net ) {
                            return 404;
            }
            if ( $host = skymonk.net ) {
                            return 404;
            }
            if ( $host ~ counter ) {
                            return 404;
            }
            if ( $host ~ pluraserver ) {
                            return 404;
            }
            if ( $host ~ apps.bittorrent.com ) {
                            return 404;
            }
            if ( $host ~ tracker ) {
                            return 404;
            }
            if ( $request_uri ~* (update|feed|announce|rss|xml|json|oauth) ) {
                            return 404;
            }
            if ( $request_uri ~* (toolbar|suggest) ) {
                            return 404;
            }
            if ( $request_filename ~ \.(ico|gif|jpg|png) ) {
                            return 404;
            }
            if ( $request_filename ~ \.(css|xml|js|swf|flv) ) {
                            return 404;
            }
            if ( $request_filename ~ \.(crl|txt|cab|msi|jar) ) {
                            return 404;
            }
            if ( $host ~ norton ) {
                            return 404;
            }
            rewrite ^ http://192.168.2.2:82/index.php redirect;
        }

location ~ \.php$ {
                try_files $uri =404;
                include /etc/nginx/fastcgi_params;
                fastcgi_pass unix:/var/run/php5-fpm.sock;
        }

}

Файл /var/www/82/index.php я создал такого типа:

<html>
<head>
...
<p class='alert-text' style='color:red;'>
Ваше устройство не зарегистрировано в системе<br>
и получило временный айпи адрес, при необходимости сообщите его оператору</p><br>
<b><p class='alert-text' style='color:red; font-size:140%;'><?php echo $_SERVER["REMOTE_ADDR"]; ?></b></p><br>
<a href='https://test.ixnfo.com/'>ЛИЧНЫЙ КАБИНЕТ</a><br>
<p class='alert-text'><b>Телефоны для справок:</b><br>
XX-XX-XX, ... <br>
<b>С уважением, Администрация ...</b><br><br></p>
...

Так как на сервере доступа я использовал для должников ipset, то для этого ipset переадресуем http запросы через iptables, разрешим доступ к серверу с nginx, биллингу и dns серверу, а все остальное запретим.

/sbin/ipset create denyip iphash
/sbin/iptables -t nat -A PREROUTING -p tcp -m multiport --dport 80 -m set --match-set denyip src -j DNAT --to-destination 192.168.5.5:81
/sbin/iptables -A FORWARD -m set --match-set denyip src -d 192.168.5.5 -p tcp --dport 81 -j ACCEPT
/sbin/iptables -A FORWARD -m set --match-set denyip src -d 192.168.5.5 -p tcp --dport 443 -j ACCEPT
/sbin/iptables -A FORWARD -m set --match-set denyip src -d 192.168.2.2 -p tcp --dport 9443 -j ACCEPT
/sbin/iptables -A FORWARD -m set --match-set denyip src -d 192.168.2.2 -p tcp --dport 53 -j ACCEPT
/sbin/iptables -A FORWARD -m set --match-set denyip src -d 192.168.2.2 -p udp --dport 53 -j ACCEPT
/sbin/iptables -A FORWARD -m set --match-set denyip src -j DROP

Либо если гостевым клиентам выдаются отдельные IP адреса, то вместо ipset укажем сеть:

iptables -t nat -A PREROUTING -s 10.0.56.0/24 -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.5.5:81

Кратко опишу процесс:

Windows при подключении к сети под «http_user_agent=Microsoft NCSI» пытается открыть страницу http://www.msftncsi.com/ncsi.txt на которой содержится текст Microsoft NCSI и получает статус 200 ОК, а также проверяет DNS сервер — определяет IP адрес для dns.msftncsi.com, который должен быть 131.107.255.255.
Если ссылка открылась и DNS ответил верно, то система считает что есть подключение к интернет, если ссылка не доступна, а DNS ответил верно — система считает что нужно авторизоваться и открывает в браузере наш captive portal.
Все эти параметры хранятся в реестре HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet, а также можно отключить эту проверку указав 0 для EnableActiveProbing.

Apple при подключении к сети два раза пытается открыть http://captive.apple.com/hotspot-detect.html, в золовке и теле странице ожидает получить текст «Success». Первый раз пытается под «http_user_agent=CaptiveNetworkSupport…».

В логах nginx можно увидеть следующие записи:

«GET /connecttest.txt HTTP/1.1» 301 178 «-» «Microsoft NCSI»
«GET /ncsi.txt HTTP/1.1» 301 178 «-» «Microsoft NCSI»
«GET /hotspot-detect.html HTTP/1.0» 302 154 «-» «CaptiveNetworkSupport-355.260.2 wispr»
«GET /generate_204 HTTP/1.1» 301 178 «-» «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36»

Подобным образом на Apache2 используя .htaccess можно сделать следующим образом:

RewriteEngine on
ErrorDocument 404 http://192.168.5.5:81/index.php

Также чтобы поисковики не индексировали страницу, можно создать файл robots.txt с содержимым:

User-agent: *
Disallow: /

Иногда в логах видел ошибки что нет файла favicon.ico, по этому можно его тоже добавить.

А также я рекомендую через iptables ограничить доступ к странице только для локальных сетей.

Смотрите также мою статью:
IPTables правила для веб-сервера
Настройка маскарадинга (NAT) в Ubuntu

Вливайтесь в общение

1 комментарий

Добавить комментарий

  1. Здравствуйте
    понравилось решение, но есть несколько вопросов….
    не все странички отрабатывает, допусти facebook microsoft
    а так же странички допустим из закладок где помимо домена еще всякой белеберда из серии microsoft.com/en-us/software-download/windows10ISO
    как нить можно решить?