最近、ネットワーク業界の巷で話題になっている”pingアスキーアート"について、少し動作原理を試してみました。ほんのさわりだけなので恐縮ですが、あくまでの個人勉強のためですね。
元ネタは、@kooshinさんによるJANOG BoF & LT Night #2 の発表資料になります。
- pingアスキーアート ( JANOG BoF & LT Night #2 の発表資料です)
- pingを打つと「にゃーん」を返すサービス、ネットワークエンジニアが開発
それにしても、湧き溢れるアイディアを実際に具体化してしまった@kooshinさんは、ほんと凄いです。
■ 試してみた、Ubuntu環境
Ubuntu 16.04.3 LTSで環境を作ってみました。
root@ubuntu:~# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.3 LTS"
■ rootユーザのpython仮想環境を作る
rootユーザでのpython環境を汚したくないので、pyenvで仮想環境を整備しておきます。
本題とは、あまり関係ないので、ここの作業は、スキップしても問題ないです。
(1) 事前に、各種パッケージをインストールしておく
tsubo@ubuntu:~$ sudo apt-get install git gcc make openssl libssl-dev libbz2-dev libreadline-dev libsqlite3-dev
(2) pyenv環境を整備する
root@ubuntu:~# git clone https://github.com/yyuu/pyenv.git ~/.pyenv
(3) rootユーザにpyenv環境変数を追加する
.bashrcに以下の環境変数を追加する
export PYENV_ROOT=$HOME/.pyenv
export PATH=$PYENV_ROOT/bin:$PATH
eval "$(pyenv init -)"
追加した環境変数を有効にする
root@ubuntu:~# source .bashrc
(4) pyenvのインストール結果を確認しておく
root@ubuntu:~# pyenv --version
pyenv 1.1.3-33-g48aa0c4
(5) python 3.6.2を有効にする
python3.6.2インストールする
root@heat:~# pyenv install 3.6.2
Downloading Python-3.6.2.tar.xz...
-> https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tar.xz
Installing Python-3.6.2...
Installed Python-3.6.2 to /root/.pyenv/versions/3.6.2
python3.6.2を有効にする
root@ubuntu:~# pyenv global 3.6.2
root@ubuntu:~# pyenv versions
system
* 3.6.2 (set by /root/.pyenv/version)
■ 各種pythonライブラリを事前にインストールする
これらのpythonライブラリ環境が必要になります。
(1) NetfilterQueueをインストールする
root@ubuntu:~# pip install NetfilterQueue
Collecting NetfilterQueue
Downloading NetfilterQueue-0.8.1.tar.gz (58kB)
100% |████████████████████████████████| 61kB 3.2MB/s
Installing collected packages: NetfilterQueue
Running setup.py install for NetfilterQueue ... done
Successfully installed NetfilterQueue-0.8.1
(2) Scapyをインストールする
root@ubuntu:~# pip install scapy-python3
Collecting scapy-python3
Downloading scapy-python3-0.21.tar.gz (2.2MB)
100% |████████████████████████████████| 2.2MB 694kB/s
Installing collected packages: scapy-python3
Running setup.py install for scapy-python3 ... done
Successfully installed scapy-python3-0.21
■ まずは、NetfilterQueue動作を確認してみる
(1) Pingサンプルアプリ配備する
まずは、NetfilterQueueに掲載されたサンプルアプリを配備します。
from netfilterqueue import NetfilterQueue
def print_and_accept(pkt):
print(pkt)
pkt.accept()
nfqueue = NetfilterQueue()
nfqueue.bind(1, print_and_accept)
try:
nfqueue.run()
except KeyboardInterrupt:
print('')
nfqueue.unbind()
(2) iptablesを設定する
root@ubuntu:~# iptables -A INPUT -p icmp -j NFQUEUE --queue-num 1
(3) 実際、サンプルアプリを起動します
root@ubuntu:~# python sample_icmp.py
(4) 別端末等から、pingをうってみると、
ttsubo-no-macbook-pro:~ ttsubo$ ping 192.168.195.204
PING 192.168.195.204 (192.168.195.204): 56 data bytes
64 bytes from 192.168.195.204: icmp_seq=0 ttl=64 time=0.409 ms
64 bytes from 192.168.195.204: icmp_seq=1 ttl=64 time=0.491 ms
64 bytes from 192.168.195.204: icmp_seq=2 ttl=64 time=0.732 ms
64 bytes from 192.168.195.204: icmp_seq=3 ttl=64 time=0.753 ms
64 bytes from 192.168.195.204: icmp_seq=4 ttl=64 time=0.400 ms
^C
--- 192.168.195.204 ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.400/0.557/0.753/0.155 ms
問題なく、pingが成功しますね。
(5) 先ほど、サンプルアプリが起動画面に、、、
root@ubuntu:~# python sample_icmp.py
ICMP packet, 84 bytes
ICMP packet, 84 bytes
ICMP packet, 84 bytes
ICMP packet, 84 bytes
ICMP packet, 84 bytes
という感じて、ICMPパケットを受信したことが確認できるようになりました。
■ つづいて、scapy動作を確認してみる
(1) Pingサンプルアプリを拡張する
ICMP EchoRequestのシーケンス番号が"5の倍数”だったら、ICMP EchoReplyを返信しないように、先ほどのサンプルアプリを改造します。
from scapy.all import *
from netfilterqueue import NetfilterQueue
def print_and_accept(pkt):
packet = IP(pkt.get_payload())
icmp = packet[ICMP]
if (icmp.seq % 5) == 0:
pkt.drop()
else:
pkt.accept()
if __name__ == "__main__":
nfqueue = NetfilterQueue()
nfqueue.bind(1, print_and_accept)
try:
nfqueue.run()
except KeyboardInterrupt:
print('')
nfqueue.unbind()
(2) 実際、サンプルアプリを起動します
root@ubuntu:~# python sample_icmp_fake.py
WARNING: No route found for IPv6 destination :: (no default route?). This affects only IPv6
(3) 別端末等から、pingをうってみると、
ttsubo-no-macbook-pro:~ ttsubo$ ping 192.168.195.204
PING 192.168.195.204 (192.168.195.204): 56 data bytes
Request timeout for icmp_seq 0
64 bytes from 192.168.195.204: icmp_seq=1 ttl=64 time=1.515 ms
64 bytes from 192.168.195.204: icmp_seq=2 ttl=64 time=1.507 ms
64 bytes from 192.168.195.204: icmp_seq=3 ttl=64 time=1.367 ms
64 bytes from 192.168.195.204: icmp_seq=4 ttl=64 time=1.383 ms
Request timeout for icmp_seq 5
64 bytes from 192.168.195.204: icmp_seq=6 ttl=64 time=1.453 ms
64 bytes from 192.168.195.204: icmp_seq=7 ttl=64 time=1.694 ms
64 bytes from 192.168.195.204: icmp_seq=8 ttl=64 time=1.301 ms
64 bytes from 192.168.195.204: icmp_seq=9 ttl=64 time=1.376 ms
Request timeout for icmp_seq 10
64 bytes from 192.168.195.204: icmp_seq=11 ttl=64 time=1.273 ms
64 bytes from 192.168.195.204: icmp_seq=12 ttl=64 time=1.358 ms
64 bytes from 192.168.195.204: icmp_seq=13 ttl=64 time=1.161 ms
64 bytes from 192.168.195.204: icmp_seq=14 ttl=64 time=1.180 ms
Request timeout for icmp_seq 15
64 bytes from 192.168.195.204: icmp_seq=16 ttl=64 time=1.305 ms
64 bytes from 192.168.195.204: icmp_seq=17 ttl=64 time=1.288 ms
^C
--- 192.168.195.204 ping statistics ---
18 packets transmitted, 14 packets received, 22.2% packet loss
round-trip min/avg/max/stddev = 1.161/1.369/1.694/0.135 ms
期待通り、icmp_seqが"5の倍数"の場合には、pingが失敗しますね。
■ 最後に、
以上、ごく一部ですが、動作確認できました。
OpenFlowとか、使わずとも、パケット制御できてしまうあたりが、とても、感銘を受けました。