📜 ⬆️ ⬇️

Setting up wifi authorization via sms under ubuntu 16.04

Hi Habr! Not so long ago, our organization faced the task of legalizing wifi access, but to continue using the system for free. (According to the Government Resolution No. 758 of July 31, 2014 and No. 801 of August 12, 2014, all public WIFI networks are required to identify users). We have 10 rooms for events (from 30 to 400 people), and on average between 4 and 12 per day, plus the constant turnover of the people and capricious users.

image

To begin, I will tell you how we have a network. If you do not go into details, then hung access points HP MSM430 (J9651), management via HP MSM760 (J9420A) and HP Gateway F1000-EI (JG214A). The choice of equipment is not successful, but we work with what we have.

It so happened that in life I loved the Windows system more, but after receiving the task, after reading a lot of articles, I came to the conclusion that * nix system is best for this purpose. The choice fell on the Ubuntu server 16.04. Then there were several days of torment, but in the end everything turned out.
')
This article is for those who love Windows, looks at Ubuntu and puts a bunch of software from scratch.

How I decided to organize everything:

There is an open network, let's call it Free. When you connect, the user is redirected to a hotspot with an authorization page. There, he is given an Internet access code and a phone number to which he must send a message (a bit unusual, but the task was to save, including via SMS). As soon as the message comes to us, Internet access immediately opens. I’ll make a reservation that it’s better to use a SIM card and a modem number MTS (not an advertisement), since they didn’t find an opportunity to send an SMS from the site without specifying the left number (although this is a problem, but in the process of solving).

What we need:


Let's start.

Installing Ubuntu Server 16.04


Here, everything is pretty trite:

  1. Create a virtual machine (2 cores, 4 GB of memory, 2 network interfaces, 30 GB disk)
  2. We swing the last distribution kit, we connect, we put ...
  3. We configure network interfaces, one looks in vlan of wifi network, the second towards the gateway

Network Setup and Forwarding Packages



We look at what network cards we have and what logical names are assigned to them:
cat /proc/net/dev 

In my case, this is eth0 and eth1:
 Inter-| Receive | Transmit face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed lo: 632643353 3624368 0 0 0 0 0 0 632643353 3624368 0 0 0 0 0 0 eth1: 8789521059 30492824 0 0 0 0 0 0 65843784529 28992970 0 0 0 0 0 0 eth0: 65798728800 56063700 0 0 0 0 0 0 8382628950 29920038 0 0 0 0 0 0 


Edit the network interface configuration file:
 nano /etc/network/interfaces 

 auto eth0 iface eth0 inet static #     address 10.66.66.6 netmask 255.255.255.240 network 10.66.66.0 broadcast 10.66.66.15 gateway 10.66.66.1 dns-nameservers 10.66.66.1 auto eth1 iface eth1 inet static #   wifi  address 10.0.87.254 netmask 255.255.248.0 network 10.0.80.0 broadcast 10.0.87.255 

Make sure that IPv6 interfaces are actually present in the system:

 ip a | grep inet 

You can also see that some applications post TCP listeners on IPv6 interfaces. You can see all ports listened in the system with the command:

 sudo ss -lnptu | sort 

To turn off IPv6 support on all network interfaces at once, open the sysctl.conf file for editing

 sudo nano -Y sh /etc/sysctl.conf 

Add lines to the end of the file to enable forwarding and disable IPv6:

 net.ipv4.ip_forward=1 net.ipv6.conf.all.disable_ipv6 = 1 

To verify that our option can be read by sysctl at boot time, run:

 sudo sysctl -p 

 /etc/init.d/networking restart 

MySQL installation


As the database server, I chose MaridDB. In terms of functionality, something is even better than MySQL, but the article is not about that.

 apt-get install mariadb-server #    mysql_secure_installation # mysql    mysql -u root use mysql; update user set plugin='' where User='root'; flush privileges; 

Check if everything started well with us:

 service mysql status 

Installing Squid with SSL support and IPv6 disable


There are many articles on how to build and install proxies, but this stage was probably the most dreary. By default, Squid without SSL support is in the Ubunt repository. I decided to rebuild, and so it took 2 days ... As a result, I got my own manual how to build the latest version 3.5.20 for x64.

We put the necessary software for the assembly:

 apt-get install git fakeroot checkinstall build-essential devscripts patch libssl-dev libgnutls28-dev apt-cache policy squid3 apt-get update apt-get build-dep squid3 

Uncomment the source repositories and add a new one:

 nano /etc/apt/sources.list deb-src http://ftp.de.debian.org/debian/ testing main contrib non-free 

The new repository, will swear on the keys, so we will immediately get them:

 gpg --keyserver keyserver.ubuntu.com --recv 8B48AD6246925553 gpg --export --armor 8B48AD6246925553 | sudo apt-key add - gpg --keyserver keyserver.ubuntu.com --recv 7638D0442B90D010 gpg --export --armor 7638D0442B90D010 | sudo apt-key add - 

Do not forget to update information about repositories:

 apt-get update 

In order not to clutter up the working folder, go to tmp and download from testing the latest version of squid with the rules for building under debian

 cd /tmp/ apt-get source squid3 

Current version 3.5.19, updated to the latest 3.5.21

 wget http://www.squid-cache.org/Versions/v3/3.5/squid-3.5.21.tar.gz tar -xf squid-3.5.21.tar.gz mkdir ./squid-3.5.21/debian/ cp -r ./squid3-3.5.19/debian/* ./squid-3.5.21/debian/ cd squid-3.5.21/ nano debian/rules 

Add lines (do not forget to specify the path to openssl.cnf, I have it / etc / ssl)

 --disable-ipv6 \ --enable-icap-client \ --enable-ssl-crtd \ --with-openssl=/etc/ssl \ 

We correct the error (constant messages in the logs: SECURITY ALERT: Host header detected for local detected ... = 443 remote = ...: *), well described in the article , with an assessment of all security risks. (The article describes about version 3.5.12, the code has changed a little here).
 nano ./src/client_side_request.cc 

We are looking for the hostHeaderIpVerify function and modify its code a bit:

 void ClientRequestContext::hostHeaderIpVerify(const ipcache_addrs* ia, const DnsLookupDetails &dns) { Comm::ConnectionPointer clientConn = http->getConn()->clientConnection; // note the DNS details for the transaction stats. http->request->recordLookup(dns); if (ia != NULL && ia->count > 0) { // Is the NAT destination IP in DNS? for (int i = 0; i < ia->count; ++i) { if (clientConn->local.matchIPAddr(ia->in_addrs[i]) == 0) { debugs(85, 3, HERE << "validate IP " << clientConn->local << " possible from Host:"); http->request->flags.hostVerified = true; http->doCallouts(); return; } debugs(85, 3, HERE << "validate IP " << clientConn->local << " non-match from Host: IP " << ia->in_addrs[i]); } } // patch for SECURITY ALERT: Host header forgery detected http->request->flags.hostVerified = true; http->doCallouts(); return; debugs(85, 3, HERE << "FAIL: validate IP " << clientConn->local << " possible from Host:"); hostHeaderVerifyFailed("local IP", "any domain IP"); } 

We confirm the patch and collect (wait about 10-15 minutes)

 dpkg-source --commit #patch update to squid 3.5.20 debuild 

We look, what packages we have gathered:

 ls -l /tmp/ | grep .deb$ 

If there are no packages, then check the folder.
 ls -l /tmp/squid3-3.5.19/ | grep .deb$ 

And we start the installation of Squid:

 apt-get install squid-langpack libdbi-perl dpkg -i squid-common_3.5.19-1_all.deb dpkg -i squid_3.5.19-1_amd64.deb dpkg -i squid3_3.5.19-1_all.deb dpkg -i squidclient_3.5.19-1_amd64.deb 

if for any reason, the installer hangs up, then reset the lock:

 fuser -vki /var/lib/dpkg/lock 

we start and check the status

 service squid start systemctl status -l squid 

in response should see something similar

 squid.service - LSB: Squid HTTP Proxy version 3.x Loaded: loaded (/etc/init.d/squid; bad; vendor preset: enabled) Active: active (running) 

Checking the installed version of Squid
 /usr/sbin/squid -v Squid Cache: Version 3.5.21 Service Name: squid Ubuntu linux 

Now let's set it up, first we will create an SSL certificate and save the default config:

 cd /etc/squid openssl req -new -newkey rsa:1024 -days 365 -nodes -x509 -keyout squidCA.pem -out squidCA.pem mv ./squid.conf ./squid.conf.default nano ./squid.conf 

The configuration file is almost unchanged from the article .

 acl localnet src 10.0.80.0/21 acl SSL_ports port 443 acl Safe_ports port 80 # http acl Safe_ports port 21 # ftp acl Safe_ports port 443 # https acl Safe_ports port 70 # gopher acl Safe_ports port 210 # wais acl Safe_ports port 1025-65535 # unregistered ports acl Safe_ports port 280 # http-mgmt acl Safe_ports port 488 # gss-http acl Safe_ports port 591 # filemaker acl Safe_ports port 777 # multiling http acl CONNECT method CONNECT dns_nameservers 10.66.66.1 http_access deny !Safe_ports http_access deny CONNECT !SSL_ports http_access allow localhost manager http_access deny manager http_access allow localnet http_access allow localhost http_access deny all #http_port 3128 #    intercept http_port 10.0.87.254:3128 intercept options=NO_SSLv3:NO_SSLv2 #    ,       #  ,   ,    ,   #    ,     ,      #   ,     =) http_port 10.0.87.254:3130 options=NO_SSLv3:NO_SSLv2 # ,  HTTPS     https_port 10.0.87.254:3129 intercept ssl-bump options=ALL:NO_SSLv3:NO_SSLv2 connection-auth=off cert=/etc/squid/squidCA.pem always_direct allow all sslproxy_cert_error allow all sslproxy_flags DONT_VERIFY_PEER #      (    .domain.com) acl blocked ssl::server_name "/etc/squid/blocked_https.txt" acl step1 at_step SslBump1 ssl_bump peek step1 # ,       ssl_bump terminate blocked ssl_bump splice all sslcrtd_program /usr/lib/squid/ssl_crtd -s /var/lib/ssl_db -M 4MB coredump_dir /var/spool/squid refresh_pattern ^ftp: 1440 20% 10080 refresh_pattern ^gopher: 1440 0% 1440 refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 refresh_pattern . 0 20% 4320 cache_dir aufs /var/spool/squid 2048 49 256 maximum_object_size 61440 KB minimum_object_size 3 KB cache_swap_low 90 cache_swap_high 95 maximum_object_size_in_memory 512 KB memory_replacement_policy lru #logfile_rotate 31 logfile_daemon /usr/lib/squid/log_db_daemon access_log daemon:/127.0.0.1:3306/base/table/user/password squid 

Create a file with a list of blocked resources

 nano ./blocked_https.txt 

I pay attention that we will write logs to the database. To do this, create a table:

 CREATE TABLE `access_log` ( `id` int(11) NOT NULL AUTO_INCREMENT, `time_since_epoch` decimal(15,3) DEFAULT NULL, `time_response` int(11) DEFAULT NULL, `ip_client` char(15) DEFAULT NULL, `ip_server` char(15) DEFAULT NULL, `http_status_code` varchar(10) DEFAULT NULL, `http_reply_size` int(11) DEFAULT NULL, `http_method` varchar(20) DEFAULT NULL, `http_url` varchar(500) DEFAULT NULL, `http_username` varchar(20) DEFAULT NULL, `http_mime_type` varchar(50) DEFAULT NULL, `squid_request_status` varchar(50) DEFAULT NULL, `squid_hier_status` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

we start and check the status

 service squid start systemctl status -l squid 

in response should see something similar

  squid.service - LSB: Squid HTTP Proxy version 3.x Loaded: loaded (/etc/init.d/squid; bad; vendor preset: enabled) Active: active (running) 

Check the ports used and the version of the installed squid

 sudo ss -lnptu | grep :3128 sudo ss -lnptu | grep :3129 sudo ss -lnptu | grep :3130 squid -version Squid Cache: Version 3.5.20 

We put USB-Redirector and modem


Since the cluster is used for HyperV 2012R2, the problem arises, namely how to plug in a modem. Our organization is used quite successfully: USB-Redirector . We put it under Ubuntu

 cd /tmp/ wget http://www.incentivespro.com/usb-redirector-linux-x86_64.tar.gz tar -xf usb-redirector-linux-x86_64.tar.gz ./usb-redirector-linux-x86_64/installer.sh install-client 

connect to the server where we connected the modem

 usbclnt -addserver 10.XXX:32032 usbclnt -autoconnect on 1 

we watch the list of all usb devices

 usbclnt -l ================= USB CLIENT OPERATION SUCCESSFUL =============== List of USB servers and devices: 1: USB server at 10.XXX:32032 Mode: auto-connect Status: connected - 7: HUAWEI Mobile Vid: 12d1 Pid: 1001 Port: 3-2 Mode: manual-connect Status: disconnected 

install modem drivers

 apt-get install usb-modeswitch usb-modeswitch-data 

connect and check if the modem is installed

 usbclnt -connect 1-7 ls /dev | grep ttyUSB 

in response must see:

 ttyUSB0 ttyUSB1 ttyUSB2 


The USB device needs to be switched to modem mode, for this we install the minicon program:
 apt-get install minicom 

Run its configuration:
 minicom -s 

Select "Configure serial port" and in the "serial port" set / dev / ttyUSB0
We do not change anything else in the settings. The following at-commands are used to switch modes of operation in huawei modems:
AT ^ U2DIAG = 0 device in modem only mode
AT ^ U2DIAG = 1 device in modem + CD-ROM mode
AT ^ U2DIAG = 255 - device in modem mode + CD-ROM + Card Reader
AT ^ U2DIAG = 256 device in modem + Card Reader
Turn on the modem only mode:
AT ^ U2DIAG = 0
In response, we get "OK". Exit the program, to do this, press Ctrl + A and Q.

Install SMS-tools


Information about the packages can be found on the developer's website .
Install and configure:

 apt-get install smstools nano /etc/smsd.conf 

find the line [GSM1]

 [GSM1] device = /dev/ttyUSB0 incoming = yes baudrate = 9600 eventhandler = /var/www/sms_recieve.php 

create an incoming SMS handler file and make it executable

 nano /var/www/sms_recieve.php chmod 755 /var/www/sms_recieve.php service smstools restart 

We configure the DHCP server


 apt-get install isc-dhcp-server nano /etc/default/isc-dhcp-server #,      dhcp  INTERFACES="eth1" sudo nano /etc/dhcp/dhcpd.conf #  authoritative; subnet 10.0.80.0 netmask 255.255.248.0 { range 10.0.80.1 10.0.86.254; option domain-name-servers 10.0.87.254; option domain-name "wifi-free"; option subnet-mask 255.255.248.0; option routers 10.0.87.254; option broadcast-address 10.0.87.255; default-lease-time 7200; #2h max-lease-time 72000; #20h } /etc/init.d/isc-dhcp-server restart 

Configuring Nginx and PHP 5.6 FPM


Since php has been updated to version 7 and in all ubuntu repositories already has php7, we add a new one and install:

 add-apt-repository ppa:ondrej/php apt-get install php5.6-cli php5.6-common php5.6-mysql php5.6-gd php5.6-fpm php5.6-cgi php-pear 

stop the installed service and edit the configuration files

 service php5.6-fpm stop nano /etc/php/5.6/fpm/php.ini cgi.fix_pathinfo = 0 post_max_size = 200M upload_max_filesize = 200M nano /etc/php/5.6/fpm/pool.d/www.conf security.limit_extensions = .php .php3 .php4 .php5 listen = /run/php/php5.6-fpm.sock listen.owner = www-data listen.group = www-data listen.mode = 0660 service php5.6-fpm start 

You can make sure that the permissions for the socket are set correctly:

 ls -la /run/php/php5.6-fpm.sock #srw-rw---- 1 www-data www-data 0 May 2 16:36 /run/php/php5.6-fpm.sock 

Checking:

 php -v PHP 5.6.23-2+deb.sury.org~xenial+1 (cli) Copyright (c) 1997-2016 The PHP Group Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies 

Go to Nginx

 apt-get install nginx nginx-extras 

The main Nginx settings are stored in the /etc/nginx/nginx.conf file.

The base site settings are stored in the / etc / nginx / sites-available / default file.

The base configuration file of the site can be placed in the / etc / nginx / sites-available / folder and then included by adding a symbolic link to this file in the / etc / nginx / sites-enabled / folder.

 touch /etc/nginx/sites-available/hotspot.domain.com ln -s /etc/nginx/sites-available/hotspot.domain.com /etc/nginx/sites-enabled/ mkdir /etc/nginx/common 

I will continue to be brief, since explanations can be read on the link . We create common server configuration files in which we describe the security, compression, caching and php settings.

 touch /etc/nginx/common/upstream nano /etc/nginx/common/upstream upstream php-fpm { # PHP5.6-FPM  server unix:/run/php/php5.6-fpm.sock; } 

 touch /etc/nginx/common/security nano /etc/nginx/common/security add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; 

 touch /etc/nginx/common/gzip nano /etc/nginx/common/gzip gzip on; gzip_disable "msie6"; gzip_comp_level 6; gzip_min_length 1100; gzip_buffers 16 8k; gzip_proxied any; gzip_types text/plain application/xml text/css text/js text/xml application/x-javascript text/javascript application/javascript application/json application/xml+rss; 

 touch /etc/nginx/common/php-fpm nano /etc/nginx/common/php-fpm #     PHP-FPM    "/etc/php/5.6/fpm/pool.d/www.conf" fastcgi_pass php-fpm; #   -  "include fastcgi_params"    include fastcgi_params; fastcgi_split_path_info ^(.+?\.php)(/.*)?$; #   "$document_root"           (. http://wiki.nginx.org/Pitfalls) fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name; # . http://trac.nginx.org/nginx/ticket/321 set $path_info $fastcgi_path_info; fastcgi_param PATH_INFO $path_info; # Additional variables fastcgi_param SERVER_ADMIN email@example.com; fastcgi_param SERVER_SIGNATURE nginx/$nginx_version; fastcgi_index index.php; 

 touch /etc/nginx/common/cache nano /etc/nginx/common/cache location ~* ".+\.(?:ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|css|swf|js|atom|jpe?g|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$" { access_log off; log_not_found off; expires max; } 

In my cases, I had a public wildcard certificate for my domain. Unpack the certificate file and set permissions

  openssl pkcs12 -in certname.pfx -nocerts -out /etc/nginx/ssl/key.pem -nodes openssl pkcs12 -in certname.pfx -nokeys -out /etc/nginx/ssl/cert.pem openssl rsa -in /etc/nginx/ssl/key.pem -out /etc/nginx/ssl/domain.key cd /etc/nginx/ssl/ chown www-data:www-data domain.key chmod 400 domain.key 

 touch /etc/nginx/common/ssl nano /etc/nginx/common/ssl ssl_certificate /etc/nginx/ssl/domain.crt; ssl_certificate_key /etc/nginx/ssl/domain.key; ssl_session_timeout 20m; #  20  ssl_session_cache shared:SSL:20m; #   20 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AE$ 

We configure our server:

 nano /etc/nginx/sites-available/hotspot.domain.com include common/upstream; server { listen 80; server_name hotspot.domain.com; root /var/www; index index.php index.html index.htm; client_max_body_size 200m; #        200 # Buffers fastcgi_buffers 64 4K; include common/security; include common/gzip; location "/" { index index.php index.html index.htm; #           try_files $uri $uri/ =404; #        ,  -   404 include common/deny; include common/cache; include common/php-fpm; } } 

and redirect from the default server (do not forget that the DNS server must resolve the name hotspot.domain.com):

 nano /etc/nginx/sites-available/default server { listen 80 default_server; #listen [::]:80 default_server; listen 443 ssl default_server; #listen [::]:443 ssl default_server; include common/ssl; rewrite ^ http://hotspot.domain.com?url=$scheme://$host$request_uri? redirect; ... } 


Configure phpmyadmin


For more convenient work with the database, install phpmyadmin.

 apt-get install phpmyadmin apt-get install mcrypt php5.6-mcrypt php5.6-mbstring php-gettext 

 touch /etc/nginx/common/phpmyadmin nano /etc/nginx/common/phpmyadmin location /phpmyadmin { root /usr/share/; index index.htm index.html index.php; location ~ ^/phpmyadmin/(.+.php)$ { try_files $uri = 404; root /usr/share/; fastcgi_pass unix:/run/php/php5.6-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $request_filename; include /etc/nginx/fastcgi_params; } location ~* ^/phpmyadmin/(.+.(html|ico|xml|css|jpg|png|js|txt|gif|jpeg))$ { root /usr/share/; } } location /phpMyAdmin { rewrite ^/* /phpmyadmin last; } 

and similarly connect to nginx

 nano /etc/nginx/sites-available/hotspot.domain.com include common/phpmyadmin; 

restart

 service nginx restart service php5.6-fpm restart 

Configuring iptables firewall


In this section, we need to restrict access to the server and wrap traffic on the proxy. To begin with, let's configure saving all rules after a reboot:

 apt-get install iptables-persistent ipset 

since in our task, we need the ipset tables to be saved, we edit the following file a little:

 nano /usr/share/netfilter-persistent/plugins.d/15-ip4tables #  save_rules() touch /etc/iptables/rules.v4 touch /etc/iptables/ipset.rules chmod 0642 /etc/iptables/ipset.rules chmod 0640 /etc/iptables/rules.v4 iptables-save > /etc/iptables/rules.v4 ipset save > /etc/iptables/ipset.rules #  load_rules() ipset restore < /etc/iptables/ipset.rules iptables-restore < /etc/iptables/rules.v4 2> /dev/null 

To save the rules on the firewall, use the command:

 netfilter-persistent save 

We use conntrack to monitor and reset established connections.

 apt-get install conntrack 

Configuring iptables rules

 #   mac-ip ipset --create authorized macipmap --network 10.0.80.0/21 ipset -L authorized #     iptables -t nat -N toSQUID iptables -t nat -N toHOTSPOT #     iptables -t nat -F PREROUTING # DNS    iptables -t nat -A PREROUTING -i eth1 -p udp --dport 53 -j DNAT --to 10.66.66.1 # ip,mac ,    squid iptables -t nat -A PREROUTING -i eth1 -m set --match-set authorized src,src -j toSQUID # ip,mac  ,     iptables -t nat -A PREROUTING -i eth1 -j toHOTSPOT iptables -t nat -F toHOTSPOT #  ,       nginx iptables -t nat -A toHOTSPOT -p tcp -m multiport --dports 80,8080 -j DNAT --to-destination 10.0.87.254:80 iptables -t nat -A toHOTSPOT -p tcp -m multiport --dports 443 -j DNAT --to-destination 10.0.87.254:443 iptables -t nat -A toHOTSPOT -j RETURN iptables -t nat -F toSQUID #      #    telegram (       squid) iptables -t nat -A toSQUID -p tcp -d 149.154.164.0/22 --dport 443 -j ACCEPT #  whatsapp iptables -t nat -A toSQUID -p tcp -m multiport --dport 4244,5242,5228,5223,5222 -j ACCEPT iptables -t nat -A toSQUID -p tcp -m multiport --dports 80,25,465,110,995,119,563,8080 -j REDIRECT --to-ports 3128 iptables -t nat -A toSQUID -p tcp -m multiport --dports 443 -j REDIRECT --to-ports 3129 iptables -t nat -A toSQUID -j RETURN # NAT    iptables -t nat -A POSTROUTING -s 10.0.80.0/21 -o eth0 -j MASQUERADE #      iptables -P INPUT ACCEPT iptables -F INPUT #   lo iptables -A INPUT -i lo -j ACCEPT #        iptables -A INPUT -i eth0 -p tcp -m multiport --dports 22,80,443 -j ACCEPT #    iptables -A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT #     iptables -A INPUT -p TCP -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p UDP -m state --state ESTABLISHED,RELATED -j ACCEPT #    iptables -A INPUT -i eth1 -p tcp -m multiport --dport 3128,3129,3130 -j ACCEPT iptables -A INPUT -i eth1 -p udp -m multiport --dport 3128,3129,3130 -j ACCEPT №    iptables -A INPUT -i eth1 -p tcp -m multiport --dports 80,443 -j ACCEPT #      iptables -P INPUT DROP #    ,    iptables -N FORWARD_AUTHORIZED iptables -F FORWARD_AUTHORIZED #   telegram iptables -A FORWARD_AUTHORIZED -p tcp -d 149.154.164.0/22 --dport 443 -j ACCEPT #   whatsapp iptables -A FORWARD_AUTHORIZED -p tcp -m multiport --dport 4244,5242,5228,5223,5222 -j ACCEPT iptables -A FORWARD_AUTHORIZED -j RETURN #      iptables -P FORWARD ACCEPT iptables -F FORWARD #   dns iptables -A FORWARD -i eth1 -p udp --dport 53 -d 10.66.66.1 -j ACCEPT #     iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT #       FORWARD_AUTHORIZED iptables -A FORWARD -i eth1 -m set --match-set authorized src,src -j FORWARD_AUTHORIZED #      iptables -P FORWARD DROP 

To catch problems we use the following commands.

 #     ip conntrack -D conntrack --orig-src 10.0.8X.XXX #     tail -f /var/log/firewall | grep 10.0.8X.XXX 

Customize php request processing files and scripts


We create tables in our database:

 SET FOREIGN_KEY_CHECKS=0; CREATE TABLE IF NOT EXISTS `mac-auth` ( `mac` char(17) NOT NULL COMMENT '  ', `code` int(6) NOT NULL COMMENT ' ', `phone` varchar(15) NOT NULL DEFAULT '' COMMENT '     ', `updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '  ', `created` datetime DEFAULT CURRENT_TIMESTAMP COMMENT ' ', UNIQUE KEY `mac` (`mac`), KEY `code` (`code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `mac-ip` ( `mac` char(17) NOT NULL COMMENT '  ', `ip` varchar(15) NOT NULL COMMENT 'ip  ', `date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ' ', KEY `mac` (`mac`), KEY `ip` (`ip`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `mac-phone` ( `mac` char(17) NOT NULL COMMENT '  ', `phone` varchar(15) NOT NULL COMMENT ' ', `date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ' ', KEY `mac` (`mac`), KEY `ip` (`phone`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ALTER TABLE `mac-ip` ADD CONSTRAINT `mac` FOREIGN KEY (`mac`) REFERENCES `mac-auth` (`mac`) ON DELETE CASCADE ON UPDATE CASCADE; SET FOREIGN_KEY_CHECKS=1; 

we create a script, at login, to check the operation of all services:

 nano /var/www/check_services.sh #!/bin/bash function check { printf %-30s "check $1" if (( $(ps -ef | grep -v grep | grep $1 | wc -l) > 0 )) then echo -e "[\033[32;1m OK \033[0m]" else echo -e "[\033[31;1m ERROR \033[0m]" fi } check dhcpd check nginx check mysql check php-fpm check smstools check squid check usbsrvd 

set launch permissions and add to start

 chmod 755 /var/www/check_services.sh nano ~/.profile /var/www/check_services.sh 

And now the sources of php files:

 nano /var/www/sms_recieve.php 

 #!/usr/bin/php <?php require_once 'hotspot/connect.php'; $sms_type = $argv[1]; $sms_file = $argv[2]; $sms_file_content = file_get_contents($sms_file); $i = strpos($sms_file_content, "\n\n"); $sms_headers_part = substr($sms_file_content, 0, $i); $sms_message_body = substr($sms_file_content, $i + 2); $sms_header_lines = split("\n", $sms_headers_part); $sms_headers = array(); foreach ($sms_header_lines as $header) { $i = strpos($header, ":"); if ($i !== false) $sms_headers[substr($header, 0, $i)] = substr($header, $i + 2); } $phone = (float)$sms_headers['From']; $code = (int)$sms_message_body; //     $interval = '30 DAY'; //$interval = '1 MINUTE'; $macs = sql_getRows('SELECT `mac` FROM `mac-auth` WHERE `code` = 1 AND `updated` < DATE_SUB(NOW(),INTERVAL '.$interval .')'); if (!empty($macs)){ $data = sql_getColumn('SELECT DISTINCT(`ip`) as `ip`,`mac` FROM `mac-ip` WHERE `mac` IN ("'.implode('","',$macs).'") ORDER BY `date` DESC','mac'); foreach ($data as $mac=>$ip){ sql_query('UPDATE `mac-auth` SET `code` = "0" WHERE `mac` IN ("'.implode('","',$macs).'")'); //    shell_exec('sudo ipset -D authorized '.$ip .','.$mac); //    ip shell_exec('sudo conntrack -D conntrack --orig-src '.$ip); } shell_exec('sudo ipset save > /etc/iptables/ipset.rules'); } echo $phone.'-'.$code; $mac = sql_getValue('SELECT `mac` FROM `mac-auth` WHERE `code` = '.$code); if ($mac){ $ip = sql_getValue('SELECT DISTINCT(`ip`) FROM `mac-ip` WHERE `mac` = "'.$mac.'" ORDER BY `date` DESC'); echo '-'.$mac.'-'.$ip; //       sql_query('INSERT `mac-phone` (`mac`,`phone`) VALUES("'.$mac.'","'.$phone.'")'); sql_query('UPDATE `mac-auth` SET `phone` = "'.$phone.'", `code` = "1" WHERE `mac` = "'.$mac.'"'); //    shell_exec('sudo ipset -A authorized '.$ip .','.$mac); shell_exec('sudo ipset save > /etc/iptables/ipset.rules'); shell_exec('sudo conntrack -D conntrack --orig-src '.$ip); } //  unlink($sms_file); ?> 

 nano /var/www/hotspot/index.php 

 <?php //     require_once 'connect.php'; // ip  $ip = ''; if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])){ $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; } if (empty($ip)) $ip = $_SERVER['REMOTE_ADDR']; //  ip  if (!preg_match('/^10\.0\.8[0-7]\.\d{1,3}$/', $ip)) { $ip = false; } //   if ($ip) $mac = trim(shell_exec("arp -a ".$ip." | awk '{print $4}'")); if (!isset($mac) || $mac == "entries") $mac = false; //      $url = $_GET['url']; //if (strpos($url, 'gstatic.com')!==false) $url = 'http://www.domain.ru'; //   header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); //    //   $error = false; if (!$mac){ $error = '    . <br/>      .<br/><font class="eng error">Error with your network card. Internet access can not be granted</font>'; } else { //,    ip    $base_ip = sql_getValue('SELECT DISTINCT(`ip`) FROM `mac-ip` WHERE `mac` = "'.$mac.'" ORDER BY `date` DESC'); if ($base_ip != $ip){ sql_query('INSERT INTO `mac-ip` (`mac`,`ip`) VALUES ("'.$mac.'","'.$ip.'")'); } //    $code = sql_getValue('SELECT `code` FROM `mac-auth` WHERE `mac` = "'.$mac.'"'); switch ($code){ case '1': //  shell_exec('sudo ipset -A authorized '.$ip .','.$mac); shell_exec('sudo ipset save > /etc/iptables/ipset.rules'); //    ip,  TOO_MANY_REDIRECTS shell_exec('sudo conntrack -D conntrack --orig-src '.$ip); header('Location: '.$url); die; break; case '': //  sql_query('INSERT INTO `mac-auth` (`mac`,`code`) VALUES ("'.$mac.'",0)'); case '0': //       //  do { $code = rand(10000,99999); } while(sql_getValue('SELECT `mac` FROM `mac-auth` WHERE `code` = "'.$code.'"')); sql_query('UPDATE `mac-auth` SET `code` = '.$code.' WHERE `mac` = "'.$mac.'"'); default: //  ,     break; } } ?> <!DOCTYPE HTML> <html> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <meta name="viewport" content="width=device-width, initial-scale=0.8, maximum-scale=1" /> </head> <body> <style type="text/css"> html, body { width: auto; margin: 0px; padding: 0px; } * { font-family: "Tahoma", sans-serif; font-size: 14px; text-align:center; font-style: normal; font-variant: normal; font-weight: normal; color: #000; } .center { width: 400px; padding: 10px; margin: auto; } .logo { background-image: url("/logo2.gif"); width: 177px; height: 209px; margin: auto; } .header { font-size: 16px; padding: 10px; } .repeat { padding: 10px; } .sms { font-size: 11px; color: #4c4b4b; padding: 10px; } .law { font-size: 11px; color: #4c4b4b; padding: 10px; } .code { font-size: 16px; font-weight: bold; } .num { font-size: 16px; font-weight: bold; } .internet-disabled { background-color: #dadbdb; color: white; padding: 7px 20px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; border: 2px solid #ffffff; border-radius: 4px; box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19); } .internet { background-color: #3e315f; color: white; padding: 7px 20px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; border: 2px solid #ffffff; border-radius: 4px; box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19); } .internet:hover { background-color: #ffffff; color: #3e315f; border: 2px solid #3e315f; box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19); } .eng { font-size: 12px; line-height: 12px; } .error { color: #d11313; } </style> <?php if (!$error) {?> <script type="text/javascript"> window.onload = function(){ window.htime = 60; check = function(){ if (window.htime <=0 ) { return true; } else { return false; } } window.htimer = window.setInterval(function(){ document.getElementById('button').innerHTML = ' ' + window.htime + ' .'; window.htime -= 1; if (window.htime <= 0) { window.clearInterval(window.htimer); document.getElementById('button').className = "internet"; document.getElementById('button').innerHTML = '  '; } }, 1000); } </script> <?php } ?> <div class="center"> <div class="logo"></div> <div class="header">     <br/>   . <font class="eng">Welcome to the open network of the Civic Chamber of the Russian Federation.</font></div> <?php if ($error) { echo '<div class="error">'.$error.'</div>';} else { ?> <div>        SMS  : <font class="code"><?php echo $code;?></font>  : <font class="num">+7 917 XXX-XX-XX.</font><br/><font class="eng">To access Internet, text this code <b><?php echo $code;?></b> to number <b>+7 917 XXX-XX-XX.</b></font></div> <div class="repeat">  SMS   : <br/><font class="eng">After you've sent SMS with code, please click this button:</font></div> <a target="_self" href="<?php echo $url;?>" id="button" class="internet-disabled" onclick="return check();"> </a> <div class="repeat">    SMS    . ,   .<br/><font class="eng">Please allow a minor delay in providing you access — delivery and processing of your SMS might take a few moments. Thank you for your patience.</font></div> <div class="sms"> SMS-     .<br/>Cost of SMS-messages is charged according to your tariff plan.</div> <div class="law">   №758  31  2014.  №801  12  2014 . -   WIFI     .<br/>We require our WiFi users to authenticate following the provisions of the Russian law, stated by enactments 758 of 31st July 2014 and 801 of 12th August 2014. </div> <?php } ?> </div> </body> </html> 

 nano /var/www/hotspot/connect.php 

 # mysql login params $mysql_host = ''; $mysql_db = ''; $mysql_login = ''; $mysql_password = ''; $sql_link = mysqli_connect($mysql_host, $mysql_login, $mysql_password, $mysql_db) or die(mysql_error()); function sql_query($sql, $unbuffered = false){ global $sql_link; $resource = $unbuffered ? mysqli_real_query($sql_link, $sql) : mysqli_query($sql_link, $sql); if (mysqli_errno($sql_link) === 1016) { if (preg_match("/'(\S*)\.MYD'\. \(errno\: 145\)/", mysqli_error($sql_link), $m)) { mysqli_unbuffered_query("REPAIR TABLE ".$m[1]); $resource = $unbuffered ? mysqli_unbuffered_query($sql_link, $sql) : mysqli_query($sql_link, $sql); } } return $resource; } function sql_getValue($sql, $unbuffered = false){ $resource = sql_query($sql, $unbuffered); $ret = false; if (is_resource($resource) || is_object($resource)) { $row = mysqli_fetch_row($resource); $ret = $row[0]; } return $ret; } function sql_getRows($sql, $use_key = false, $unbuffered = false){ $resource = sql_query($sql, $unbuffered); $ret = false; if (is_resource($resource) || is_object($resource)) { $row = true; while ($row) { $row = mysqli_fetch_array($resource, MYSQLI_ASSOC); if (!$row) continue; $_row = $row; if ($use_key) { if (isset($_row[$use_key])) { $link = &$ret[$_row[$use_key]]; $link = $_row; } } else { $link = &$ret[]; $link = (count($_row) == 1) ? array_shift($_row) : $_row; } } } return $ret; } function sql_getColumn($sql, $id_field = 'id', $unbuffered = false){ $resource = sql_query($sql, $unbuffered); $ret = false; if (is_resource($resource) || is_object($resource)) { $row = true; while ($row) { $row = mysqli_fetch_array($resource, MYSQLI_ASSOC); if (!$row) continue; $_row = $row; $id = $_row[$id_field]; unset($_row[$id_field]); $value = current($_row); $ret[$id] = $value; } } return $ret; } function sql_getRow($sql, $unbuffered = false){ $resource = sql_query($sql, $unbuffered); $ret = false; if (is_resource($resource) || is_object($resource)) { $ret = mysqli_fetch_assoc($resource); } return $ret; } 

, sudoers iptables php

 nano /etc/sudoers smsd ALL=(ALL) NOPASSWD: /sbin/ipset smsd ALL=(ALL) NOPASSWD: /sbin/iptables www-data ALL=(ALL) NOPASSWD: /sbin/ipset www-data ALL=(ALL) NOPASSWD: /sbin/iptables smsd ALL=(ALL) NOPASSWD: /usr/sbin/conntrack www-data ALL=(ALL) NOPASSWD: /usr/sbin/conntrack 

. , . Thanks for attention!

Source: https://habr.com/ru/post/307338/


All Articles