labunix's blog

labunixのラボUnix

debian jessieでダミーNICを作成してみる。

■debian jessieでダミーNICを作成してみる。
 kernelにはモジュールとして組み込まれているので、
 必要に応じて呼び出す必要があります。

$ lsb_release -d
Description:	Debian GNU/Linux 8.2 (jessie)

$ sudo apt-get install -y kernel-package
$ grep CONFIG_DUMMY= /usr/share/kernel-package/Config/config* | \
    awk '/amd64/{print}'
/usr/share/kernel-package/Config/config.amd64:CONFIG_DUMMY=m

$ sudo modinfo dummy
filename:       /lib/modules/3.16.0-4-amd64/kernel/drivers/net/dummy.ko
alias:          rtnl-link-dummy
license:        GPL
depends:        
intree:         Y
vermagic:       3.16.0-4-amd64 SMP mod_unload modversions 
parm:           numdummies:Number of dummy pseudo devices (int)

■まずはdummyモジュールを手動で呼び出して[dummy0]を作成
 依存関係はないので、[modprobe]でモジュールを使えるようにする。
 IPを指定して[dummy0]interfaceを起動するだけ。

$ lsmod | grep dummy || sudo modprobe -v dummy;lsmod | grep dummy
insmod /lib/modules/3.16.0-4-amd64/kernel/drivers/net/dummy.ko 
dummy                  12717  0 

$ sudo ifconfig dummy0 10.10.10.254/24 up

■interfaceに指定したIPが割り当てられている確認と、
 pingによる疎通確認

$ ip a list dummy0 | awk '/inet /{print}'
    inet 10.10.10.254/24 brd 10.10.10.255 scope global dummy0

$ ping -c 3 10.10.10.254
PING 10.10.10.254 (10.10.10.254) 56(84) bytes of data.
64 bytes from 10.10.10.254: icmp_seq=1 ttl=64 time=0.092 ms
64 bytes from 10.10.10.254: icmp_seq=2 ttl=64 time=0.059 ms
64 bytes from 10.10.10.254: icmp_seq=3 ttl=64 time=0.091 ms

--- 10.10.10.254 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.059/0.080/0.092/0.018 ms

■MACアドレスについての蛇足
 MACアドレスはランダムに自動で割り当てられる。
 ベンダーコードは敢えて外しているように見えるが、
 被る場合は自分で作成しても良い。

$ ip a list dummy0 | awk '/link.ether/{print substr ($2,1,8);}'
6a:d6:19

 MACアドレス検索
 http://mac.uic.jp/tool

 MAC Address Generator
 http://www.miniwebtool.com/mac-address-generator/

■MACアドレスは毎回自動で割り当てられても面倒なので、
 上記で手動で割り当てたものをそのまま使う。

$ echo "test -f /etc/network/if-pre-up.d/dummy || \
        echo '/sbin/modprobe -a dummy' | \
        sudo tee /etc/network/if-pre-up.d/dummy" | \
    sed -e "1h;1G;" -e '/-a/s/-a/-r/;/pre-up/s/pre-up/post-down/;/pre-up/s/pre-up/post-down/' | sh

$ sudo grep dummy0 /etc/network/interface >/dev/null 2>&1 || \
    echo -e "\
auto dummy0\niface dummy0 inet static
\tpre-up modprobe -a dummy
\tpost-down modprobe -r dummy
\taddress 10.10.10.254
\tnetmask 255.255.255.0
\tnetwork 10.10.10.0
\tbroadcast 10.10.10.255
\thwaddress `ip a list dummy0 | awk '/link.ether/{print $2}'`" | \
    sudo tee -a /etc/network/interfaces
auto dummy0
iface dummy0 inet static
	pre-up modprobe -a dummy
	post-down modprobe -r dummy
	address 10.10.10.254
	netmask 255.255.255.0
	network 10.10.10.0
	broadcast 10.10.10.255
	hwaddress 6a:d6:19:ac:9c:21

■自動設定に必要な[ifdown][ifup]で操作出来るようになる。
 [/etc/network/run/ifstate]で管理されるようにもなる。

$ awk '/dummy/{print "before",$0}' /etc/network/run/ifstate; \
  sudo ifdown dummy0 && \
  sudo ifup dummy0; \
  awk '/dummy/{print "after",$0}' /etc/network/run/ifstate
before dummy0=dummy0
after dummy0=dummy0

$ ip a list dummy0 | awk '/link.ether/ || /inet /{print $2}'
6a:d6:19:ac:9c:21
10.10.10.254/24

■モジュール呼び出し時に[numdummies]078つのダミーNICを使えるようにする。
 [dummy0]1つだけなら良いのだけど、
 複数の場合はモジュール読み込みを削除されては困る。

$ sudo sed -i -e 's/.*modprobe .*dummy/&0/g' /etc/network/interfaces
$ sudo grep dummy0 /etc/network/interfacesauto dummy0
iface dummy0 inet static
	pre-up modprobe -a dummy0
	post-down modprobe -r dummy0

$ test -f /etc/modprobe.d/dummy.conf || \
  echo "options dummy numdummies=8" | sudo tee /etc/modprobe.d/dummy.conf && \
  for n in `seq 0 7`;do echo "alias dummy${n} dummy";done | \
  sudo tee -a /etc/modprobe.d/dummy.conf
options dummy numdummies=8
alias dummy0 dummy
alias dummy1 dummy
alias dummy2 dummy
alias dummy3 dummy
alias dummy4 dummy
alias dummy5 dummy
alias dummy6 dummy
alias dummy7 dummy

■[modprobe]の設定確認

$ sudo modprobe -c | grep dummy
alias dummy0 dummy
alias dummy1 dummy
alias dummy2 dummy
alias dummy3 dummy
alias dummy4 dummy
alias dummy5 dummy
alias dummy6 dummy
alias dummy7 dummy
options dummy numdummies=8
alias rtnl_link_dummy dummy
alias snd_seq_client_14 snd_seq_dummy
alias symbol:ata_dummy_port_info libata
alias symbol:ata_dummy_port_ops libata
alias symbol:i2c_new_dummy i2c_core

■[dummy[1-7]を手動で作成して[ifup][ifdown]で操作出来るように設定する。

$ for n in `seq 1 7`;do \
   /sbin/ifconfig 2>&1 | grep dummy${n} > /dev/null || \
   sudo ifconfig dummy${n} 10.10.10.${n}/24 up; \
   sudo grep dummy${n} /etc/network/interface >/dev/null 2>&1 || \
   echo -e "\
auto dummy${n}
iface dummy${n} inet static
\tpre-up modprobe -a dummy${n}
\tpost-down modprobe -r dummy${n}
\taddress 10.10.10.${n}
\tnetmask 255.255.255.0
\tnetwork 10.10.10.0
\tbroadcast 10.10.10.255
\thwaddress `ip a list dummy${n} | awk '/link.ether/{print $2}'`" | \
    sudo tee -a /etc/network/interfaces;done > /dev/null

■作成したdummy[0-7]の疎通確認

$ for n in `seq 1 7` 254;do ping -c 1 10.10.10.${n};done | grep from
64 bytes from 10.10.10.1: icmp_seq=1 ttl=64 time=0.082 ms
64 bytes from 10.10.10.2: icmp_seq=1 ttl=64 time=0.064 ms
64 bytes from 10.10.10.3: icmp_seq=1 ttl=64 time=0.058 ms
64 bytes from 10.10.10.4: icmp_seq=1 ttl=64 time=0.063 ms
64 bytes from 10.10.10.5: icmp_seq=1 ttl=64 time=0.077 ms
64 bytes from 10.10.10.6: icmp_seq=1 ttl=64 time=0.078 ms
64 bytes from 10.10.10.7: icmp_seq=1 ttl=64 time=0.061 ms
64 bytes from 10.10.10.254: icmp_seq=1 ttl=64 time=0.046 ms

■それぞれのMACアドレスを確認

$ for n in `seq 0 7`;do \
    echo -n "dummy${n}="; \
    ip a list dummy${n} | awk '/link.ether/{print $2}';done
dummy0=6a:d6:19:ac:9c:21
dummy1=22:64:c0:37:bb:6f
dummy2=7e:51:6b:96:c7:cc
dummy3=76:48:e8:d0:46:b7
dummy4=0e:2d:9e:bc:11:51
dummy5=96:c8:2d:1d:1f:bc
dummy6=fe:b5:ae:bd:c9:e3
dummy7=96:e7:34:a0:79:a2

■[ifconfig]で作成したNICを停止。

$ for n in `seq 0 7`;do echo "ifconfig dummy${n} down";done | sudo sh

■[ifup][ifdown]で起動、停止を確認。

$ for n in `seq 0 7`;do echo "ifup dummy${n}";done | sudo sh
$ for n in `seq 0 7`;do echo -n "dummy${n}=";ip a list dummy${n} | awk '/link.ether/{print $2}';done
dummy0=6a:d6:19:ac:9c:21
dummy1=22:64:c0:37:bb:6f
dummy2=7e:51:6b:96:c7:cc
dummy3=76:48:e8:d0:46:b7
dummy4=0e:2d:9e:bc:11:51
dummy5=96:c8:2d:1d:1f:bc
dummy6=fe:b5:ae:bd:c9:e3
dummy7=96:e7:34:a0:79:a2
$ ip a list | awk '/inet 10.10.10./{print}'
    inet 10.10.10.254/24 brd 10.10.10.255 scope global dummy0
    inet 10.10.10.1/24 brd 10.10.10.255 scope global dummy1
    inet 10.10.10.2/24 brd 10.10.10.255 scope global dummy2
    inet 10.10.10.3/24 brd 10.10.10.255 scope global dummy3
    inet 10.10.10.4/24 brd 10.10.10.255 scope global dummy4
    inet 10.10.10.5/24 brd 10.10.10.255 scope global dummy5
    inet 10.10.10.6/24 brd 10.10.10.255 scope global dummy6
    inet 10.10.10.7/24 brd 10.10.10.255 scope global dummy7
$ for n in `seq 0 7`;do echo "ifdown dummy${n}";done | sudo sh
$ ip a list | awk '/inet 10.10.10./{print}'

■例えば以下のようにMACアドレスは連番の方が良いと思う場合もある。
 ベンダーコードは24bitなので、残り24bitすべてを計算しても良いが、
 サブネットマスクが/24なので[00][ff]を除いた[01~fe]の範囲に限定する。

$ for n in `seq 1 6` 254;do echo "$n" | awk '{printf "6a:d6:19:ac:9c:%02x\n",$0}'; done
6a:d6:19:ac:9c:01
6a:d6:19:ac:9c:02
6a:d6:19:ac:9c:03
6a:d6:19:ac:9c:04
6a:d6:19:ac:9c:05
6a:d6:19:ac:9c:06
6a:d6:19:ac:9c:07
6a:d6:19:ac:9c:fe

■一度[/etc/network/interfaces]のdummy[0-7]の設定を削除して、
 以下のコマンドで再登録。

$ for n in 254 `seq 1 7`;do \
    MAC=$(echo "$n" | awk '{printf "6a:d6:19:ac:9c:%02x\n",$0}'); \
   echo -e "\
auto dummy$(($n%254))
iface dummy$(($n%254)) inet static
\tpre-up modprobe -a dummy$(($n%254))
\tpost-down modprobe -r dummy$(($n%254))
\taddress 10.10.10.${n}
\tnetmask 255.255.255.0
\tnetwork 10.10.10.0
\tbroadcast 10.10.10.255
\thwaddress ${MAC}" | \
    sudo tee -a /etc/network/interfaces;done > /dev/null

■[ifup]して[ping]で疎通確認、
 IP/MACアドレスを確認して[ifdown]で停止の
 一連の作業をワンライナーで行う。

$ for n in 254 `seq 1 7`;do \
    echo "echo [dummy$(($n%254))]; \
          ifup dummy$(($n%254)); \
          ping -c 1 10.10.10.${n} | grep from; \
          ip a list dummy$(($n%254)) | awk '/inet / || /link.ether/ {print}'; \
          ifdown dummy$(($n%254))"; \
  done | sudo sh
[dummy0]
64 bytes from 10.10.10.254: icmp_seq=1 ttl=64 time=0.039 ms
    link/ether 6a:d6:19:ac:9c:fe brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.254/24 brd 10.10.10.255 scope global dummy0
[dummy1]
64 bytes from 10.10.10.1: icmp_seq=1 ttl=64 time=0.038 ms
    link/ether 6a:d6:19:ac:9c:01 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.1/24 brd 10.10.10.255 scope global dummy1
[dummy2]
64 bytes from 10.10.10.2: icmp_seq=1 ttl=64 time=0.046 ms
    link/ether 6a:d6:19:ac:9c:02 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.2/24 brd 10.10.10.255 scope global dummy2
[dummy3]
64 bytes from 10.10.10.3: icmp_seq=1 ttl=64 time=0.044 ms
    link/ether 6a:d6:19:ac:9c:03 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.3/24 brd 10.10.10.255 scope global dummy3
[dummy4]
64 bytes from 10.10.10.4: icmp_seq=1 ttl=64 time=0.044 ms
    link/ether 6a:d6:19:ac:9c:04 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.4/24 brd 10.10.10.255 scope global dummy4
[dummy5]
64 bytes from 10.10.10.5: icmp_seq=1 ttl=64 time=0.046 ms
    link/ether 6a:d6:19:ac:9c:05 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.5/24 brd 10.10.10.255 scope global dummy5
[dummy6]
64 bytes from 10.10.10.6: icmp_seq=1 ttl=64 time=0.047 ms
    link/ether 6a:d6:19:ac:9c:06 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.6/24 brd 10.10.10.255 scope global dummy6
[dummy7]
64 bytes from 10.10.10.7: icmp_seq=1 ttl=64 time=0.043 ms
    link/ether 6a:d6:19:ac:9c:07 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.7/24 brd 10.10.10.255 scope global dummy7