add some old posts

This commit is contained in:
2026-09-13 14:18:25 +03:00
parent d5ab80e7da
commit 358d56da30
132 changed files with 3595 additions and 0 deletions
@@ -0,0 +1,223 @@
---
title: 'Captive portal'
date: '22:22 26-11-2014'
publish_date: '22:22 26-11-2014'
taxonomy:
category:
- Blog
tag:
- Linux
- gelonet.ru
---
Собираю инфу по реализации Captive порталов для WiFI сетей.
Вот, первая пташка.
[Captive portal собственными руками](https://habr.com/ru/sandbox/79059/)
> Каждый из нас подключался к беспроводной сети (аэропорты, кафе и тд) где необходимо согласится с некоторыми условиями или пройти авторизации прежде чем начинать пользоваться интернетом. Такая технология называется captive portal.
>
> В мою задачу входило создать captive portal где каждому пользователю раз в 30 минут будет показываться определенный сайт (реклама), и пока он не нажмет «кнопочку» «далее» интернета не будет.
>
> Для создания нам понадобится:
> Wifi-точка доступа любая (на практике можно использовать и проводной интернет)
> Маршрутизатор на любой *nix системе (в моем случае это debian wheezy)
>
>
> Краткое описание принципа работы
> Любой пакет пришедший на маршрутизатор маркируем
> Любой запрос на 80 порт (пакеты уж маркированны) перенаправляем на нужную нам страницу
> При «авторизации»(нажатии кнопки далее) пользователя добавляем его мак в исключения и разрешаем доступ в интернет
> Скрипт вычисляет у кого прошел лимит времени и удаляет данного клиента.
>
>
>
> У нас имеется маршрутизатор на базе debian, где eth0 — локальная сеть в моем случае (192.168.11.0/24), eth0:1 — интерфейс который смотрит в интернет.
>
> Настройку интерфейсов мы пропустим, это каждый выполнит сам. Сразу перейдем к настройке iptables, я обычно прописываю iptables в rc.local:
> /etc/rc.local
> IPTABLES="/sbin/iptables"
> EBTABLES="/sbin/ebtables"
> DHCP="67:68"
> SSH="22"
> WWW="80"
>
> $IPTABLES -t mangle -F
> $IPTABLES -F
>
> $IPTABLES -A INPUT -i lo -j ACCEPT
> #ssh
> $IPTABLES -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
> # разрешаем серверу и клиентам dns гугла
> $IPTABLES -A INPUT -s 8.8.8.8 -j ACCEPT
> $IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
>
> # создаем правило интернет
> $IPTABLES -N internet -t mangle
> $IPTABLES -t mangle -A PREROUTING -j internet
> #добавляем разрешенные маки в исключения путем добавления их в Return
> awk 'BEGIN { FS="\t"; } { system("$IPTABLES -t mangle -A internet -m mac --mac-source "$4" -j RETURN"); }' /var/lib/users
> #маркируем все пакеты
> $IPTABLES -t mangle -A internet -j MARK --set-mark 99
> # все маркированные пакеты которые идут на 80 порт отправляем на наш сервер
> $IPTABLES -t nat -A PREROUTING -m mark --mark 99 -p tcp --dport 80 -j DNAT --to-destination 192.168.11.38
> #дроппаем все маркированное
> #$IPTABLES -t filter -A FORWARD -m mark --mark 99 -j DROP
> #dns
> $IPTABLES -t filter -A INPUT -s 8.8.8.8 -j ACCEPT
> #http
> $IPTABLES -t filter -A INPUT -p tcp --dport 80 -j ACCEPT
> #port dns
> $IPTABLES -t filter -A INPUT -p udp --dport 53 -j ACCEPT
> #drop
> $IPTABLES -t filter -A INPUT -m mark --mark 99 -j DROP
> echo "1" > /proc/sys/net/ipv4/ip_forward
> #настройка нат
> $IPTABLES -A FORWARD -i eth0 -o eth0:1 -m state --state ESTABLISHED,RELATED -j ACCEPT
> $IPTABLES -A FORWARD -i eth0:1 -o eth0 -j ACCEPT
> $IPTABLES -t nat -A POSTROUTING -o eth0 -j MASQUERADE
>
> На этом конфигурация iptables заканчивается и переходим к странице которую получает пользователь: /var/lib/index.php
> <?php
>
> $server_name = "192";
> $domain_name = "168.11.38";
> $site_name = "Wireless Network";
>
> // arp
> $arp = "/usr/sbin/arp";
>
> // файл где хранятся текущие пользователи
> $users = "/var/lib/users";
>
> // Check if we've been redirected by firewall to here.
> // If so redirect to registration address
> if ($_SERVER['SERVER_NAME']!="$server_name.$domain_name") {
> header("location:http://$server_name.$domain_name/index.php?add="
> .urlencode($_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']));
> exit;
> }
>
> // получаем и добавляем мак пользователя
> $mac = shell_exec("$arp -a ".$_SERVER['REMOTE_ADDR']);
> preg_match('/..:..:..:..:..:../',$mac , $matches);
> @$mac = $matches[0];
> if (!isset($mac)) { exit; }
>
> if (!isset($_POST['email']) || !isset($_POST['name'])) {
> // Name or email address not entered therefore display form
> ?>
> <h1>Welcome to <?php echo $site_name;?></h1>
> To access the Internet you must first enter your details:<br><br>
> <form method='POST'>
> <table border=0 cellpadding=5 cellspacing=0>
> <tr><td>Your full name:</td><td><input type='text' name='name'></td></tr>
> <tr><td>Your email address:</td><td><input type='text' name='email'></td></tr>
> <tr><td></td><td><input type='submit' name='submit' value='Submit'></td></tr>
> </table>
> </form>
> <?php
> } else {
> enable_address();
> }
>
>
> function enable_address() {
>
> global $name;
> global $email;
> global $mac;
> global $users;
> // время добавления пользователя храним в unixtime
> file_put_contents($users,$_POST['name'].";".$_POST['email'].";"
> .$_SERVER['REMOTE_ADDR'].";$mac;".date("U")."\n",FILE_APPEND + LOCK_EX);
>
> // добавляем правило в iptables
> exec("sudo iptables -I internet 1 -t mangle -m mac --mac-source $mac -j RETURN");
> // The following line removes connection tracking for the PC
> // This clears any previous (incorrect) route info for the redirection
> exec("sudo rmtrack ".$_SERVER['REMOTE_ADDR']);
>
> sleep(1);
> header("location:http://".$_GET['add']);
> exit;
> }
>
> // Function to print page header
> function print_header() {
>
> ?>
> <html>
> <head><title>Welcome to <?php echo $site_name;?></title>
> <META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
> <LINK rel="stylesheet" type="text/css" href="./style.css">
> </head>
>
> <body bgcolor=#FFFFFF text=000000>
> <?php
> }
>
> // Function to print page footer
> function print_footer() {
> echo "</body>";
> echo "</html>";
>
> }
>
> ?>
>
> Данная страница может быть любой, смысл лишь в том, чтобы получить мак пользователя и добавить его в iptables.
>
> В текущий момент получилась следующая схема:
> Iptables автоматически редиректит любой запрос на 80 порт на нашу страницу
> пользователь вводит свое имя и почту, скрипт php получает мак пользователя и добавляет в iptables правило исключения для этого мака
> Php скрипт складывает все данные пользователей (имя, почта, время добавления) в файл /var/lib/users
>
> Осталось только сделать скрипт который будет:
> удалять правило из iptables для мака у которого вышло время
> удалять из файла данные по этому пользователю
>
>
> Так как мои знания в программировании довольно плачевны был написан простенький скрипт на перле:
> #!/usr/bin/perl
>
> $file = "/var/lib/users";
> $curtime = time();
> # время "бана" 30 минут время в секундах так как считаем потом в unixtime
> $bantime = 1800;
> $tmpfile = "out.tmp";
>
> open(my $data, '<', $file) or die "Could not open '$file' $!\n";
> while (my $line = <$data>) {
> chomp $line;
> (@field) = split(";", $line);
>
>
> #прибавляем время "бана" ко времени когда зашел пользователь (4 поле в нашем случае) получаем время когда нужно удалить пользователя
> if (defined($exptime)) { undef $exptime; }
> $result = $field[4];
> $exptime = $bantime + $result;
> # такая коснтрукция потому что перл не хотел прибавлять $field[4] + $bantime
>
> # если текущее время больше времени для удаления, удаляем мак и перезаписываем файл
> if ($curtime > $exptime) {
> #printf "BINGO\n";
> system "iptables -D internet -t mangle -m mac --mac-source $field[3] -j RETURN";
> # system "rm /var/lib/users";
>
> }
> else {
> printf "$field[3]; $exptime\n";
>
> open SF, ">>$tmpfile";
> printf SF "$field[0];$field[1];$field[2];$field[3];$field[4]\n";
> close SF;
> system "mv /root/out.tmp /var/lib/users";
> system "chown www-data. $file";
> }
>
> }
>
>
>
> > Все, задача выполенна, модифицируя файлик index.php можем показывать пользователю релкаму, смешные видео, заставлять его оставлять свою почту и т.д.