Приведу пример настройки переадресации клиентов без денег на 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