【セキュリティ意識を高めよう】Raspberry Pi 4を使ってフリーWi-Fiのリスクを学べるWi-Fiアクセスポイントを構築

85
【セキュリティ意識を高めよう】Raspberry Pi 4を使ってフリーWi-Fiのリスクを学べるWi-Fiアクセスポイントを構築

本記事でわかること

この記事では、Raspberry Pi 4を使ってフリーWi-Fiアクセスポイントを構築し、HTTP通信を行った際にセキュリティ注意喚起ページを表示する方法を解説します。これにより、ユーザーはHTTP通信のリスクやセキュリティ意識の重要性を理解できるようになります。

対象読者

  • ネットワークに関する基礎的な理解を持つ人。(IPアドレス、DNS、DHCP、ポート)
    ただ、知識がなくても、手順通りに実装すれば動作させることはできますので、その場合は都度都度調べながら読んでみてください。

完成像(この記事を読んでできる成果物)

Raspberry Pi 4を使って構築したWi-Fiアクセスポイントに対してHTTP通信(通信内容を暗号化していない)が発生した際、それをこちらで用意した独自のWebページへ誘導させます。また、独自のWebページに入力した個人情報がアクセスポイント側(Raspberry Pi 4)でつつ抜けになっていることを明らかにします。

1. 作成したフリーWi-Fiにつなぎ、http:// ではじまるURLにアクセスしようとすると、、
2. このような誘導サイトが表示され、、

3. 情報を入力すると、、情報がフリーWi-Fi側で筒抜けになってしまう!!(以下ログの最終行)

Serving at port 8080
Path: /
Headers: Host: 192.168.18.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: ja-JP
Connection: keep-alive
Path: /submit
Headers: Host: 192.168.18.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36
Content-Length: 47
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: ja-JP
Connection: keep-alive
Name: Taro Yamada, Email: taro.yamada@example.com

アーキテクチャ



画像が小さくて見づらい場合は、以下をご参照ください。
https://link.excalidraw.com/readonly/imABIRm9fIjYNEPmvc1L

必要なもの

  • Raspberry Pi 4(Raspbian OS、またはRaspberry Pi OSがインストール済)
    OSのセットアップ方法参考リンク:https://sozorablog.com/raspberrypi_initial_setting/
  • LANケーブル1本
  • LANポートがあるWi-Fiルーター(インターネット接続有)
  • インストールするソフト:hostapd, dnsmasq, iptables, python3

1. 基本設定

まず、Raspberry Pi 4の電源を入れ、インターネットがつながっているルーターとLANケーブルでつなげてください。(LANケーブルで使うネットワークインターフェース(eth0)のIPアドレス設定は、ルーター側DHCP機能を利用します。)

インターネットに、接続できたことを確認したら、アクセスポイント構築に必要なパッケージをインストールします。
※インターネット接続を確認するには、適当にブラウザでインターネットとつながるかどうか試してみてください。

sudo apt update
sudo apt install hostapd dnsmasq iptables python3
  • hostapd:Wi-Fiアクセスポイントを構築するためのソフトウェアです。これにより、Raspberry Piをルーターのように動作させ、他のデバイスを接続させることができます。

  • dnsmasq:DHCP(IPアドレスの自動割り当て)とDNSの役割を持つソフトウェアです。接続デバイスに対してRaspberry PiからIPアドレスを割り当て、接続を管理します。
    →DNS解説参考リンク:https://www.xdomain.ne.jp/column/about-dns/
    →DHCP解説参考リンク:https://www.hcnet.co.jp/column/detail47.html

  • iptables:ファイアウォールやパケットフィルタリング機能を持つツールです。ここではNAT(ネットワークアドレス変換)やポートフォワーディングの設定に使います。
    →NAT解説参考リンク:https://baremetal.jp/blog/2023/09/08/1298/
    →ポートフォワーディング解説参考リンク:https://www.idcf.jp/words/port-forwarding.html

  • python3:PythonでWebサーバーを起動し、特定のページを表示するために使用します。

2. アクセスポイントの設定(hostapd)

/etc/hostapd/hostapd.confを作成し、以下の内容を記載します。この設定によって、Raspberry PiがWi-Fiアクセスポイントとして動作するようになります。以下のコマンドをターミナルで実行してください。

sudo nano /etc/hostapd/hostapd.conf

以下を入力してください。SSIDはご自身で決めてください。

interface=wlan0
ssid=ここにSSID名を入力
hw_mode=g
channel=7
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
rsn_pairwise=CCMP 
  • interface:使用するWi-Fiインターフェース(ここではwlan0)を指定します。
  • ssid:Wi-Fiのネットワーク名です。
  • hw_mode:Wi-Fiの動作モード(gモード)を指定します。
  • channel:使用するチャンネル番号です。周辺のWi-Fiと干渉しないように設定します。
  • auth_algs:認証アルゴリズムを指定します。ここでは1(WPA)を使用しています。

hostapdのサービスを有効化して、起動します。

sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo systemctl start hostapd

3. IPアドレス、ネットワークインターフェースの設定

Raspberry PiのWi-Fiインターフェース(wlan0)に固定IPアドレスを設定します。これにより、接続するデバイスがRaspberry PiのIPアドレスを経由してネットワークにアクセスできるようになります。

/etc/dhcpcd.confに以下の内容を追加します。以下のコマンドをターミナルで実行し、内容を入力してください。

sudo nano /etc/dhcpcd.conf

以下を追加。

interface wlan0
static ip_address=192.168.18.1/24
nohook wpa_supplicant
  • interface wlan0:Wi-Fiインターフェースwlan0に対する設定です。
  • static ip_address:アクセスポイントのIPアドレスです。今回は、(192.168.18.1/24)を指定します。
  • nohook wpa_supplicant:通常のWi-Fi接続で必要なwpa_supplicantを無効化し、アクセスポイントモードに設定します。
    【参考】wpa_supplicantとは、クライアントとして、アクセスポイントに対する接続を要求するソフトウェアのことです。
    https://www.macnica.co.jp/business/semiconductor/articles/qualcomm/142744/

4. DHCPとDNSサーバーの設定(dnsmasq)

dnsmasqを使用して、接続するデバイスにIPアドレスを割り当てるDHCPサーバーを構築します。これにより、デバイスが自動でRaspberry Piに接続できます。

sudo nano /etc/dnsmasq.confを実行し、以下を記述します。

interface=wlan0
dhcp-range=192.168.18.100,192.168.18.200,255.255.255.0,24h
dhcp-option=option:router,192.168.18.1 # Raspberry PiのIPアドレス
dhcp-option=option:dns-server,192.168.18.1 # Raspberry PiのIPアドレス

※# 以降は入力しないでください。

  • dhcp-range:接続デバイスに割り当てるIPアドレスの範囲(192.168.18.100~192.168.18.200)を指定します。
  • dhcp-option:option:routerとoption:dns-serverでルーターとDNSサーバーとしての役割を設定します。

dnsmasqの設定を反映するために再起動します。

sudo systemctl restart dnsmasq

→【再】DNS解説参考リンク:https://www.xdomain.ne.jp/column/about-dns/
→【再】DHCP解説参考リンク:https://www.hcnet.co.jp/column/detail47.html

5. NATの設定

NAT(ネットワークアドレス変換)は、異なるネットワーク間で通信を行うために必要です。今回は、wlan0インターフェース(クライアントに電波を飛ばす)にが担うネットワークと、eth0インターフェース(インターネットとつながっている)が担うネットワークをつなげます。Raspberry Piがインターネットに接続できるようにし、接続デバイスも外部ネットワークにアクセスできるようにします。

echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

さらに、iptablesでNATの設定を行います。

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
  • POSTROUTING:Raspberry Piを通して外部ネットワークにパケットを送るときにアドレスを変換します。
  • FORWARD:Raspberry Piを通過するパケットを許可します。

この設定により、接続したデバイスはRaspberry Piをアクセスポイントとしてインターネットにアクセスできるようになります。

6. ポートフォワーディング設定

HTTP通信(ポート80)を任意のポート(今回は8080)にリダイレクトさせます。これにより、HTTPリクエストが独自に用意したページに誘導されます。

sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp --dport 80 -j REDIRECT --to-port 8080
  • PREROUTING:Raspberry PiのWi-Fiインターフェースwlan0に届くHTTPリクエストをポート8080にリダイレクトするルールです。
  • REDIRECT --to-port 8080:ポート80のリクエストをPythonサーバーが待機しているポート8080に転送します。

7. 誘導先Webサーバーの設定(Pythonを利用)

Pythonの簡易的なWebサーバー起動ライブラリを使い、HTTP通信を行うユーザーに対して注意喚起ページを表示します。以下のスクリプトは、HTTP通信の内容をログに記録し、カスタマイズしたHTMLを返します。Pythonスクリプトを任意の箇所に配置し、ログインページは固定で、/var/www/htmlに配置してください。

Python(Webサーバー起動スクリプト)

from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    def log_request_details(self):
        print(f"Path: {self.path}")
        print(f"Headers: {self.headers}")

    def do_GET(self):
        self.log_request_details()
        if self.path == '/':
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            with open('/var/www/html/login.html', 'rb') as file:
                self.wfile.write(file.read())

    def do_POST(self):
        self.log_request_details()
        if self.path == '/submit':
            content_length = int(self.headers['Content-Length'])
            post_data = self.rfile.read(content_length)
            data = parse_qs(post_data.decode())
            name = data.get('name', [''])[0]
            email = data.get('email', [''])[0]

            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            response_content = f"""
            <html>
            <body>
                <h1>{name}さんの情報は監視されています!</h1>
            </body>
            </html>
            """
            self.wfile.write(response_content.encode())
            print(f"Name: {name}, Email: {email}")

httpd = HTTPServer(('0.0.0.0', 8080), SimpleHTTPRequestHandler)
print("Serving at port 8080")
httpd.serve_forever()
  • do_GET:HTTPリクエストを受信し、カスタムページを返す処理。
  • do_POST:フォーム送信時のPOSTリクエストを処理し、受け取ったデータをログに記録。

    誘導先ページ(HTML)

<!DOCTYPE html>
 <html>
 <head>
     <title>Login</title>
 </head>
 <body>
     <div class="container">
         <h2>内容を見るには、お客さま情報が必要です。</h2>
         <form action="/submit" method="post">
             <label for="name">お名前(ローマ字):</label>
             <input type="text" id="name" name="name">
             <label for="email">メールアドレス:</label>
             <input type="text" id="email" name="email">
             <input type="submit" value="Submit">
         </form>
     </div>
 </body>
 </html>

Pythonスクリプトを実行します。以下コマンドを入力してください。

python3 pythonスクリプト名.py

これにて、Raspberry Pi 4がアクセスポイントとして機能し、HTTP通信を特定のHTMLページ(注意喚起ページ)にリダイレクトされ、入力フォームで送信された情報はPythonの実行ログに流れるようになります。HTTPS通信は通常通りに機能し、HTTP通信のみがカスタムHTMLページにリダイレクトされるようになります。

試してみる

作成したフリーWi-Fiを実際に動かしてみましょう。Raspberry Pi側は、ターミナル上でPythonの実行ログが見れる状態にしておいてください。

  1. スマートフォンで、設定したSSIDを探し、接続します。
  2. 接続したら、まずは、HTTPS通信を利用したサイトを閲覧してみましょう。(URLがhttpsから始まるページです。)例:https://www.jurabi.jp/
  3. 次に、HTTP通信を利用したサイトを閲覧してみましょう。(URLがhttpから始まるページです。)例:http://abehiroshi.la.coocan.jp/ (阿部寛さんのHP。アクセス後の情報漏洩に関しては自己責任でお願いします。)
  4. 用意した誘導サイトが表示されるはずです。入力フォームに名前とメールアドレスを入力してみましょう。
  5. Raspberry Pi側でPythonの実行ログを確認してみましょう。以下のようなログがターミナルに表示されます。
    Serving at port 8080
    Path: /
    Headers: Host: 192.168.18.1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    Accept-Encoding: gzip, deflate
    Accept-Language: ja-JP
    Connection: keep-alive
    Path: /submit
    Headers: Host: 192.168.18.1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36
    Content-Length: 47
    Content-Type: application/x-www-form-urlencoded
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    Accept-Encoding: gzip, deflate
    Accept-Language: ja-JP
    Connection: keep-alive
    Name: Taro Yamada, Email: taro.yamada@example.com

    最終行で、入力した個人情報が筒抜けになっている!!

まとめ(動作原理とHTTP通信のリスクについて)

今回の記事で構築したRaspberry Pi 4を使ったフリーWi-Fiアクセスポイントは、特にHTTP通信の危険性をユーザーに実感してもらうための仕組みです。以下、システムの動作とHTTP通信のリスクについて解説します。

  1. アクセスポイントの役割
    Raspberry Piを利用してWi-Fiアクセスポイントを構築することで、接続したユーザーのインターネット通信をRaspberry Pi経由で行うようにしています。hostapdとdnsmasqを組み合わせ、接続デバイスに自動的にIPアドレスを割り当て、通信管理が行えるように設定しました。

  2. HTTP通信のリダイレクト
    このアクセスポイントは、HTTP通信(ポート80)を一旦Pythonサーバーへと転送しています。このため、HTTPを利用したすべての通信はRaspberry Pi上の指定されたWebページにアクセスされ、ユーザーに対して警告ページが表示されます。これは、iptablesを利用してポート80の通信をポート8080にリダイレクトする設定を加えることで実現しています。

  3. Pythonスクリプトでデータが筒抜けになる仕組み
    Pythonスクリプトでは、ユーザーから送信されたデータ(名前やメールアドレス)を受け取り、ログに記録する機能が組み込まれています。この仕組みにより、ユーザーが入力した個人情報が「筒抜け」になることを示すのです。具体的には、do_POSTメソッドがフォームのデータを解析し、ユーザーが入力した情報を取得・表示しています。これにより、ユーザーはHTTP通信で送信した情報が第三者に簡単に取得される危険性を実際に体験することができます。

  4. HTTP通信のリスク
    HTTP(Hypertext Transfer Protocol)は暗号化されていないため、第三者に通信内容が読み取られる可能性があります。例えば、Wi-Fiアクセスポイントを経由した通信内容が平文(暗号化されていない状態)で流れるため、悪意ある者が中間に入りデータを傍受する(スニッフィング)ことが可能です。このため、パスワードや個人情報などの重要なデータはHTTP通信では簡単に漏洩してしまいます。

結論:フリーWi-Fiには注意が必要

今回の実験で、HTTP通信を通じて送信された情報が容易に傍受されてしまうことが確認できました。入力フォームに送信された個人情報(名前やメールアドレス)がそのまま表示されるログからもわかるように、HTTP通信では情報が暗号化されずに送信されるため、第三者に読み取られるリスクが高いです。

特に、カフェや公共施設などで利用できるフリーWi-Fiは、利便性が高い反面、このように通信内容が簡単に傍受されてしまう危険性もあります。したがって、フリーWi-Fi利用時には必ずHTTPS通信を使う、もしくは個人情報の送信を避けるなどの対策を講じることが重要です。

今回作ったフリーWi-Fiのアーキテクチャ



画像が小さくて見づらい場合は、以下をご参照ください。
https://link.excalidraw.com/readonly/imABIRm9fIjYNEPmvc1L

トラブルシューティング

hostapdが立ち上がらない場合

筆者の環境で、wlan0にアクセスポイント情報を設定し、hostapdを再起動しようとすると、立ち上がらない問題が発生しました。その際は、wlan0インターフェースを再起動してください。

sudo rfkill unblock wifi
sudo rfkill unblock all
sudo ifconfig wlan0 up
sudo ip link set wlan0 up

このコマンドでは、wifiインターフェースの利用制限を解除して、その後wlan0を立ち上げ直しています。

その他ご連絡・ご質問等ございましたらJurabi品川までご連絡お待ちしております。
shinagawa@jurabi.jp