以前、Windows10 + Scapyを簡単にさわってみました。
Windows10にScapyをインストールする - メモ的な思考的な
もう少し詳しくScapyをさわってみたいと思い、何か作ろうと考えました。
作る題材を探していたところ、書籍「ルーター自作でわかるパケットの流れ」に出会いました。
ルーター自作でわかるパケットの流れ ~ソースコードで体感するネットワークのしくみ:書籍案内|技術評論社
- 作者: 小俣 光之
- 出版社/メーカー: 技術評論社
- 発売日: 2011/07/09
- メディア: 単行本(ソフトカバー)
- 購入: 4人 クリック: 130回
- この商品を含むブログ (12件) を見る
書籍ではC言語を使ってパケットを扱い、ブリッジやルーターを自作していました。パケットを扱うならScapyでも書けるのではと思いました。
そこで、Python2 + Scapyを使って、Raspberry Pi 2 Model B をブリッジにできるか試してみました。
目次
環境
今回は 192.168.10.0/24
のローカル環境にて
の役割を持たせました。
ネットワーク構成
----------------------------------------- Mac (`en0` : WiFi) ----------------------------------------- | | ----------------------------------------- (無線) 無線LANアクセスポイント (スイッチ) ----------------------------------------- | | ----------------------------------------- (`eth0` : オンボードLANアダプタ) Raspberry Pi 2 Model B (`eth1` : 外付けUSB有線LANアダプタ) ----------------------------------------- | | ----------------------------------------- (オンボードLANアダプタ) Windows10 -----------------------------------------
ネットワークアダプタ設定
明示的に設定したネットワークアダプタ設定です。
なお、以降の表記は
- 無線LANアクセスポイント = 無線LAN AP
- Raspberry Pi 2 Model B = ラズパイ
- DGW = デフォルトゲートウェイ
とします。
機器 | アダプタ | IPアドレス | DGW | DNS |
---|---|---|---|---|
Mac | en0 | 192.168.10.101/24 | 192.168.10.1 | 192.168.10.1 |
無線LAN AP | 192.168.10.1/24 | |||
ラズパイ | eth0 | 192.168.10.50/24 | 192.168.10.1 | |
ラズパイ | eth1 | |||
Windows | 192.168.10.201/24 | 192.168.10.1 | 192.168.10.1 |
各機器の構成
- Mac OS X 10.11.6
- Python2 or Python3
- 疎通確認のためにHTTPサーバを立てるのに使用
- Python2 or Python3
- Raspberry Pi 2 Model B
- Raspberry Pi 2 Model Bの初期セットアップ用
- Windows10
- curlをインストール済
- HTTPの疎通確認のため
- めんどくさくなければ、ブラウザでも可
- curlをインストール済
なお、Scapyは2つあります。
- Python2版(本家)
- Python3対応版(scapy-python3)
ただ、何かあった時に
- 自分の書き方が悪い
- scapy-python3の非互換なところ
の区別がつかないため、今回はPython2版のScapyを使いました。
ラズパイのセットアップ
以前ラズパイは使用していましたが、2015/7以降使っていなかったため、改めてラズパイをセットアップします。
メモリカードの調達
以前は、bootとrootを分けたファイルシステムを使っていました。
Raspberry Pi 2 + Raspbianで、microSDをboot、USBメモリをrootというファイルシステムにする - メモ的な思考的な
ただ、セットアップするのがめんどうなので、相性の良さそうなメモリカードを調達することにしました。
安価で入手しやすく動作報告の多いものを調べたところ、東芝の MSDAR40N08G
が良さそうでした。
年末年始だったので家電量販店に行きましたが、普通に売っていました。
Raspbianのインストール
公式のインストールガイドに従い、Raspbianをインストールしました。
Installing operating system images - Raspberry Pi Documentation
Raspbianの初期セットアップ
ラズパイに microSDを挿入し、外付けキーボード・HDMI接続のモニタ・LANケーブル・外付けUSB有線LANアダプタをつないで、GUIで初期セットアップします。
USBマウスは手元に無かったものの、キーボード操作で何とかなりました。
キーボードレイアウトの変更
OADG 109A
を選びました。
vimのインストール
pi@raspberrypi:~ $ sudo apt-get update pi@raspberrypi:~ $ sudo apt-get install vim
ネットワークアダプタに固定IPアドレス割り当て
今回はブリッジなため、ラズパイのネットワークアダプタにはIPアドレスがいらない気がしました。
ただ、SSHを使ってMac上のターミナルからPythonコードを書きたいため、ラズパイのネットワークアダプタにIPアドレスを割り当てます。
設定前のラズパイのネットワークアダプタを見ると
pi@raspberrypi:~ $ ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 ... eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 ...
でした。
今回は、ラズパイのオンボードLANアダプタをMacに接続するため、 eth0
に固定IPアドレスを割り当てます。
以前ラズパイに固定IPアドレスを割り当てた時は、 /etc/network/interfaces
に追加していました。
Raspberry Pi 2 Model BにRaspbianをセットアップした - メモ的な思考的な
ただ、現在はDebian Stretch (Linux 4.9 カーネル)がベースなため、設定ファイルが /etc/dhcpcd.conf
に変更となっています。
pi@raspberrypi:~ $ vi /etc/dhcpcd.conf # 末尾に以下を追加 interface eth0 static ip_address=192.168.10.50/24 static routers=192.168.10.1 static domain_name_servers=192.168.10.1
設定を反映・確認します。
# 設定を反映 pi@raspberrypi:~ $ sudo service dhcpcd reload sending signal HUP to pid 323 # 設定内容を確認 pi@raspberrypi:~ $ ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.10.50 netmask 255.255.255.0 broadcast 192.168.10.255
SSHを有効化
raspi-config
にて有効化します。
pi@raspberrypi:~ $ sudo raspi-config
5 Interfacing Options > P2 SSH
にて enabled
にします。
MacからラズパイにSSHしてみましたが、問題なく動作しました。
$ ssh pi@192.168.10.50 pi@192.168.10.50's password: (raspberryと入力) Linux raspberrypi 4.9.59-v7+ #1047 SMP Sun Oct 29 12:19:23 GMT 2017 armv7l The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Mon Jan 1 23:37:50 2018 from 192.168.10.101 SSH is enabled and the default password for the 'pi' user has not been changed. This is a security risk - please login as the 'pi' user and type 'passwd' to set a new password. pi@raspberrypi:~ $
Scapyのインストール
ラズパイでScapyを実行する場合、 sudo python <scapyのコード>
とします。
そのため、Scapyはsudoでインストールします。
# pythonのバージョンを確認 pi@raspberrypi:~ $ sudo python --version Python 2.7.13 # Scapyのインストール (env) pi@raspberrypi:~ $ sudo pip install scapy Collecting scapy Downloading scapy-2.3.3.tgz (1.4MB) 100% |████████████████████████████████| 1.4MB 84kB/s Building wheels for collected packages: scapy Running setup.py bdist_wheel for scapy ... done Stored in directory: /root/.cache/pip/wheels/bd/cf/05/d5abc9b4434f39ffe231517dfb8dab96241fef6a99459051f9 Successfully built scapy Installing collected packages: scapy Successfully installed scapy-2.3.3
以上でラズパイのセットアップは完了です。
疎通確認の準備
MacでローカルHTTPサーバを起動
ブリッジを介しても通信できるか確認するため、MacでPythonのHTTPサーバを起動しておきます。
# Python2の場合 $ python -m SimpleHTTPServer # Python3の場合 $ python -m http.server
Windowsから通信できないことを確認
WindowsからMacのPython HTTPサーバへcurlを実行し、通信できないことを確認します。
> curl -m5 http://192.168.10.101:8000 curl: (28) Connection timed out after 5015 milliseconds
Scapyの「bridge_and_sniff」関数でラズパイをブリッジ化
ここまででラズパイの準備ができました。次はラズパイをScapyでブリッジにしてみます。
Scapyで便利な関数がないかを探したところ、 scapy/scapy/sendrecv.py
に bridge_and_sniff()
関数がありました。
https://github.com/secdev/scapy/blob/v2.3.3/scapy/sendrecv.py#L638
そこで、ラズパイ上に以下のファイルを作成し、ブリッジにできるかを試してみます。
scapy_bridge_and_sniff.py
# -*- coding: utf-8 -*- from scapy.sendrecv import bridge_and_sniff if __name__ == '__main__': print '>----- enable bridge -----' bridge_and_sniff('eth0', 'eth1') print '<----- disable bridge -----'
続いて、上記のファイルを実行します。rootでないと動作しないため、 sudo
を忘れずに行います。
pi@raspberrypi:~/router_jisaku $ sudo python scapy_bridge_and_sniff.py >----- enable bridge -----
なお、今回はタイムアウトを5秒( -m 5
) としました。ただ、通信状況によっては5秒以内には完了しないため、必要に応じてタイムアウトを延長します。
>curl -m5 http://192.168.10.101:8000 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> ... </html>
HTMLが返ってきました。通信できたようです。
Mac上のHTTPサーバのログにも通信ログがありました。
192.168.10.201 - - [02/Jan/2018 10:30:59] "GET / HTTP/1.1" 200 -
スクリプト scapy_bridge_and_sniff.py を停止した時の挙動を見てみます。
ラズパイにて Ctrl + C
でスクリプトを停止します。
pi@raspberrypi:~/router_jisaku $ sudo python scapy_bridge_and_sniff.py >----- enable bridge ----- ^C<----- disable bridge -----
>curl -m5 http://192.168.10.101:8000 curl: (28) Connection timed out after 5000 milliseconds
接続できなくなっていました。
以上より、Python2 + Scapyで、Raspberry Pi 2 Model B をブリッジにできました。
ただ、今回はScapyの bridge_and_sniff()
関数を使うだけだったので、もう少し他の実装を考えてみます。
ソースコード
GitHubに上げました。scapy_python2/bridge/scapy_bridge_and_sniff.py
が今回のファイルです。
https://github.com/thinkAmi-sandbox/syakyo-router_jisaku