Ubuntu 16.04でのSMSを介したwifi認証の設定

こんにちはHabr! 少し前まで、私たちの組織はWi-Fiアクセスを合法化するという課題に直面していましたが、将来的にはシステムの使用は無料になりました。 (2014年7月31日の政府決定第758号および2014年8月12日の第801号によれば、すべてのパブリックWIFIネットワークはユーザーを認証する必要があります)。 イベントには10​​のホール(30〜400人)があり、1日あたり平均4〜12パスに加えて、一定の人と気まぐれなユーザーの流れがあります。



画像






まず、ネットワークがどのように構成されているかを説明します。 詳細に入ることなく、HP MSM430アクセスポイント(J9651)、HP MSM760(J9420A)およびHP F1000-EIゲートウェイ(JG214A)を介した制御がハングアップします。 機器の選択は成功しませんが、私たちは持っているものを使って作業します。



人生で私はWindowsシステムにもっと夢中になりましたが、仕事を受けて、たくさんの記事を読んで、* nixシステムがこれに最適であるという結論に達しました。 選択はUbuntuサーバー16.04で行われました。 その後、数日間の苦しみがありましたが、最終的にはすべてがうまくいきました。



この記事は、Windowsを愛し、Ubuntuを見て、一からソフトウェアをインストールする人を対象としています。



すべてを整理することにしたので:



オープンなネットワークがあります。無料と呼びましょう。 接続すると、ユーザーは認証ページでホットスポットにリダイレクトされます。 そこで彼は、インターネットへのアクセスコードと、メッセージの送信先の電話番号を与えられます(少し変わっていますが、タスクはSMSを含めて保存することでした)。 メッセージが到着するとすぐに、インターネットアクセスがすぐに開きます。 予約します。左の番号を指定せずにサイトからSMSを送信する機能を見つけられなかったため、MTSとモデムの番号(広告ではない)を使用することをお勧めします(これは問題ですが、解決中です)。



必要なもの:





始めましょう。



Ubuntu Server 16.04をインストールします



ここにあるものはすべて非常にありふれたものです。



  1. 仮想マシンを作成します(2コア、4 GBのメモリ、2つのネットワークインターフェイス、30 GBのディスク)
  2. 最新のディストリビューションをダウンロードし、接続し、インストールします...
  3. ネットワークインターフェイスを設定します。1つはvlanネットワークwifiで、2つ目はゲートウェイに向かっています


ネットワーク設定とパケット転送





使用しているネットワークカードと、それらに割り当てられている論理名を確認します。

cat /proc/net/dev
      
      





私の場合、これらはeth0と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
      
      







ネットワークインターフェイスを構成するためのファイルを編集します。

 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
      
      





システムに実際にIPv6インターフェイスがあることを確認します。



 ip a | grep inet
      
      





また、IPv6インターフェースでTCPリスナーがハングしているアプリケーションもあります。 次のコマンドを使用して、システムでリッスンされているすべてのポートを表示できます。



 sudo ss -lnptu | sort
      
      





すべてのネットワークインターフェイスでIPv6サポートを一度に無効にするには、sysctl.confファイルを開いて編集します



 sudo nano -Y sh /etc/sysctl.conf
      
      





ファイルの最後に、転送を有効にしてIPv6を無効にする行を追加します。



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





ブート時にsysctlがオプションを読み取れることを確認するには、次を実行します:



 sudo sysctl -p
      
      





 /etc/init.d/networking restart
      
      





MySQLのインストール



データベースサーバーとして、MaridDBを選択しました。 機能性の面では、MySQLはいくつかの点でさらに優れていますが、この記事はそれについてではありません。



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





すべてが順調に起動したかどうかを確認します。



 service mysql status
      
      





SSLを使用してSquidをインストールし、IPv6を無効にする



プロキシの構築およびインストール方法に関する記事は多数ありますが、この段階はおそらく最も退屈なものでした。 デフォルトでは、ubuntuリポジトリにはSSLサポートなしのSquidが含まれています。 再構築することを決めたので、2日が経過しました...その結果、x64で最新バージョン3.5.20をアセンブルする方法に関するマニュアルを入手しました。



アセンブリに必要なソフトウェアを配置します。



 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
      
      





ソースリポジトリにコメントして、新しいリポジトリを追加しましょう。



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





新しいリポジトリはキーを誓うので、すぐにそれらを取得します。



 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 -
      
      





リポジトリ情報を更新することを忘れないでください:



 apt-get update
      
      





作業フォルダーを乱雑にしないために、tmpに移動し、debianでのアセンブリのルールを使用して最新バージョンのsquidをテストしてダウンロードします



 cd /tmp/ apt-get source squid3
      
      





現在のバージョン3.5.19、最新の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
      
      





行を追加します(openssl.cnfへのパスを指定することを忘れないでください、/ etc / sslがあります)



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





エラー(ログ内の一定のメッセージ:セキュリティアラート:ローカルヘッダーで偽造が検出されました= ...:443リモート= ...:*)を修正し、すべてのセキュリティリスクを評価します。 (記事ではバージョン3.5.12について説明していますが、コードはここで少し変更されています)。

 nano ./src/client_side_request.cc
      
      





hostHeaderIpVerify関数を探しており、そのコードをわずかに変更しています。



 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"); }
      
      





パッチを確認して収集します(約10〜15分待ちます)



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





収集したパッケージを確認します。



 ls -l /tmp/ | grep .deb$
      
      





パッケージがない場合は、フォルダーを確認してください
 ls -l /tmp/squid3-3.5.19/ | grep .deb$
      
      





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
      
      





何らかの理由でインストーラーがハングした場合、ロックをリセットします。



 fuser -vki /var/lib/dpkg/lock
      
      





実行してステータスを確認する



 service squid start systemctl status -l squid
      
      





応答で同様のものが表示されるはずです



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





Squidのインストール済みバージョンの確認

 /usr/sbin/squid -v Squid Cache: Version 3.5.21 Service Name: squid Ubuntu linux
      
      





それをセットアップして、最初にSSL証明書を作成し、デフォルトの設定を保存しましょう:



 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
      
      





構成ファイル。 記事からほとんど変更されていません。



 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
      
      





ブロックされたリソースのリストを含むファイルを作成する



 nano ./blocked_https.txt
      
      





データベースにログを書き込むことに注意してください。 これを行うには、テーブルを作成します。



 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;
      
      





実行してステータスを確認する



 service squid start systemctl status -l squid
      
      





応答で同様のものが表示されるはずです



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





使用されているポートとインストールされているsquidのバージョンを確認する



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





USBリダイレクターとモデムを入れます



クラスターはHyperV 2012R2で使用されるため、問題が発生します。つまり、モデムをどのように接続するのかということです。 私たちの組織では、 USB-Redirectorを非常によく使用しています 。 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
      
      





モデムが接続されているサーバーに接続します



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





すべてのUSBデバイスのリストを参照してください



 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
      
      





モデムドライバーをインストールする



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





接続し、モデムがインストールされているかどうかを確認します



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





応答では次のように表示されます



 ttyUSB0 ttyUSB1 ttyUSB2
      
      







USBデバイスをモデムモードに切り替える必要があります。これには、miniconプログラムを配置します。

 apt-get install minicom
      
      





セットアップを開始します。

 minicom -s
      
      





「シリアルポートを設定」を選択し、「シリアルポート」の項目にput / dev / ttyUSB0

設定で他の変更は行いません。 次のatコマンドは、Huaweiモデムの動作モードを切り替えるために使用されます。

AT ^ U2DIAG = 0-モデム専用モードのデバイス

AT ^ U2DIAG = 1モデムモードのデバイス+ CD-ROM

AT ^ U2DIAG = 255モデムモードのデバイス+ CD-ROM +カードリーダー

AT ^ U2DIAG = 256モデムデバイス+カードリーダー

モデムのみのモードをオンにします。

AT ^ U2DIAG = 0

応答として、「OK」を取得します。 プログラムを終了します。このためには、Ctrl + AおよびQを押します。



SMSツールをインストールする



パッケージに関する情報は開発者のWebサイトで見つけることができます。

インストールと構成:



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





行[GSM1]を見つけます



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





受信SMSハンドラファイルを作成し、実行可能にします



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





DHCPサーバーを構成する



 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
      
      





NginxおよびPHP 5.6 FPMの構成



phpはバージョン7に更新されており、php7はすべてのubuntuリポジトリに既にあるため、新しいリポジトリを追加して設定します。



 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
      
      





インストールされたサービスを停止し、構成ファイルを編集します



 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
      
      





ソケットのアクセス権が正しく設定されていることを確認できます。



 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
      
      





私たちはチェックします:



 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
      
      





Nginxに移動



 apt-get install nginx nginx-extras
      
      





基本的なNginx設定は/etc/nginx/nginx.confファイルに保存されます。



基本サイトの設定は、ファイル/ etc / nginx / sites-available / defaultに保存されます。



サイトの基本設定ファイルを/ etc / nginx / sites-available /フォルダーに配置し、このファイルへのシンボリックリンクを/ etc / nginx / sites-enabled /フォルダーに追加して含めるのが一般的です。



 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
      
      





ここで説明を見つけることができるので、私はさらに簡単になります 。 セキュリティ、圧縮、キャッシュ、およびphpの設定を記述する一般的なサーバー構成ファイルを作成します。



 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; }
      
      





私の場合、ドメインのパブリックワイルドカード証明書がありました。 証明書ファイルを解凍し、アクセス権を設定します



  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$
      
      





サーバーを構成します。



 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; } }
      
      





そして、デフォルトサーバーからリダイレクトを行います(DNSサーバーが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; ... }
      
      







phpmyadminを構成する



データベースの操作をより便利にするには、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; }
      
      





同様にnginxに接続します



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





再起動した



 service nginx restart service php5.6-fpm restart
      
      





iptablesファイアウォールの構成



このセクションでは、サーバーへのアクセスを制限し、プロキシでトラフィックをラップする必要があります。 開始するには、再起動後にすべてのルールの保存を設定しましょう。



 apt-get install iptables-persistent ipset
      
      





タスクではipsetテーブルを保存する必要があるため、次のファイルをわずかに修正します。



 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
      
      





ルールをファイアウォールに保存するには、次のコマンドを使用します:



 netfilter-persistent save
      
      





確立された接続を監視およびリセットするには、conntrackを使用します



 apt-get install conntrack
      
      





iptablesルールを構成する



 #   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
      
      





問題をキャッチするには、次のコマンドを使用します



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





PHPリクエスト処理ファイルとスクリプトを設定します



データベースにテーブルを作成します。



 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;
      
      





システムの入り口で、すべてのサービスの動作を確認するスクリプトを作成します。



 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
      
      





起動権限を設定し、追加して開始



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





そして今ソースPHPファイル:



 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; }
      
      





さて、今度は、iptablesをphpからsudoersに制御する権限を追加します



 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
      
      





それだけです このシステムは現在1か月稼働していますが、飛行は正常です。ご清聴ありがとうございました!



All Articles