Date

манипуляции с IP адресами

Python

Почему Python? Напишу об этом отдельную заметку. В двух словах - он "скриптовый", он "динамически типизирован", он нативен в любой линухе. Этого достаточно?

IPython

Нет, Стив Джобс не имеет никакого отношения к ipython. IPython - это очень крутая натюненная интерактивная консолька для пайтона, которая умеет автокомплитить, смотреть внутрь метода, нативные линуксовые команды (ls, pwd, grep), та и вообще только для крутых пацанов. Работать будем в ней консольно, она отлично для этого подходит. Еще есть браузерный вариант, но он больше для демонстраций графичков для научных сотрудников и всего такого.

Давайте решим первую задачку.

List all IP from subnet

В данном случае все очевидно, тут можно отлично закостылить, но мы не будем. Вместо этого запустим ipython и импортируем netaddr:

from netaddr import *

Крутяк. Теперь можем юзать, все что там внутри.

У нас задача - сделать список всех адресов в нужной подсети. Этим грешат абсолютно все онлайн штуки, которые показывают range - от и до. Нам это не интересно)

ip = IPNetwork('172.16.35.0/22')

В данном случае - наша маска это /22. Совсем не очевидно как считать это на листочке, тем более что это находится между октетов. Маска в десятичной системе будет выглядеть как 255.255.252.000 и вмещает она в себя аж целых 1024 адреса. Не плохо.

Предлагаю узнать побольше информации о этой сети, которую netaddr может нам любезно предоставить.

    In [12]: ip.network
    Out[12]: IPAddress('172.16.32.0') # адрес нашей сети
    In [12]: ip.broadcast
    Out[12]: IPAddress('172.16.35.255') # адрес широковещательного адреса нашей сети
    In [14]: ip.hostmask
    Out[14]: IPAddress('0.0.3.255') # инвертированная маска сети
    In [15]: ip.size
    Out[15]: 1024 # количество узлов в сети 

У всех этих методов есть подметод bits, например:

    In [16]: ip.broadcast.bits()
    Out[16]: '10101100.00010000.00100011.11111111' # мажорство

Вернемся к задачке, вот ее решение:

In [17]: for ip in IPNetwork('172.16.35.0/22'):
   ....:     print '%s' % ip

Так выглядит вывод команды:

    172.16.32.0
    172.16.32.1
    172.16.32.2
    172.16.32.3
    172.16.32.4
    172.16.32.5
    172.16.32.6
    ...
    ...
    ...
    172.16.35.251
    172.16.35.252
    172.16.35.253
    172.16.35.254
    172.16.35.255

Кто не верит, что netaddr посчитал правильно - без проблем, садитесь за калькулятор, и пересчитывайте. Удачи, бро!

Кстати, это все абсолютно так же работает и с IPv6 (и это афигительно просто):

In [18]: for ip in IPNetwork('2001:19f0:5001:1d::1/126'):
   ....:     print '%s' % ip
   ....:
2001:19f0:5001:1d::
2001:19f0:5001:1d::1
2001:19f0:5001:1d::2
2001:19f0:5001:1d::3

На самом деле хостер мне выдал /64, но их я генерировать не буду, потому что их 18446744073709552000 - а это, между прочим, многовато.

Вообще, /64 выдавать должны всем:

/64: the basic size of a single subnet: LAN, WAN, block of addresses for web virtual hosts, etc... "Normal" subnets are > never expected to be any smaller (longer prefix) than /64. No subnets are ever expected to be larger (shorter prefix) > than /64 since a /64's worth of host addresses is way more than we can imagine needing.

Невзначай скажу, что эту информацию можно успешно использовать для хороших и не очень хороших вещей)

Например, вот так:

    In [19]: for ip in IPNetwork('2001:19f0:5001:1d::1/124'):
       ....:     print 'ip -6 addr add %s/128 dev eth0' % ip
       ....:
    ip -6 addr add 2001:19f0:5001:1d::/128 dev eth0
    ip -6 addr add 2001:19f0:5001:1d::1/128 dev eth0
    ip -6 addr add 2001:19f0:5001:1d::2/128 dev eth0
    ip -6 addr add 2001:19f0:5001:1d::3/128 dev eth0
    ip -6 addr add 2001:19f0:5001:1d::4/128 dev eth0
    ip -6 addr add 2001:19f0:5001:1d::5/128 dev eth0
    ip -6 addr add 2001:19f0:5001:1d::6/128 dev eth0
    ip -6 addr add 2001:19f0:5001:1d::7/128 dev eth0
    ip -6 addr add 2001:19f0:5001:1d::8/128 dev eth0
    ip -6 addr add 2001:19f0:5001:1d::9/128 dev eth0
    ip -6 addr add 2001:19f0:5001:1d::a/128 dev eth0
    ip -6 addr add 2001:19f0:5001:1d::b/128 dev eth0
    ip -6 addr add 2001:19f0:5001:1d::c/128 dev eth0
    ip -6 addr add 2001:19f0:5001:1d::d/128 dev eth0
    ip -6 addr add 2001:19f0:5001:1d::e/128 dev eth0
    ip -6 addr add 2001:19f0:5001:1d::f/128 dev eth0

Это можно копипасить прямо в консоль. И, кстати, любой апп, который работает с сетью, умеет биндиться на интерфейс, или IP адрес. К примеру:

curl --interface '2001:19f0:5001:1d::f/128' http://www.google.com/search?q=mykolaichenko.github.io

Самое важное

В умелых руках и палка топор.


Comments

comments powered by Disqus