LoginSignup
13
9

More than 5 years have passed since last update.

pingを打つと「にゃーん」を返すサービスについての便乗ネタです

Last updated at Posted at 2017-09-10

最近、ネットワーク業界の巷で話題になっている”pingアスキーアート"について、少し動作原理を試してみました。ほんのさわりだけなので恐縮ですが、あくまでの個人勉強のためですね。

元ネタは、@kooshinさんによるJANOG BoF & LT Night #2 の発表資料になります。

それにしても、湧き溢れるアイディアを実際に具体化してしまった@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に掲載されたサンプルアプリを配備します。

sample_icmp.py
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を返信しないように、先ほどのサンプルアプリを改造します。

sample_icmp_fake.py
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とか、使わずとも、パケット制御できてしまうあたりが、とても、感銘を受けました。

13
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
9