CIDR計算ツール
ネットワークの設定を行っていた際、IPアドレスのCIDR表記(10.0.0.50/28など)が登場して、ぱっと見では実際のIPアドレス範囲を判断できずに難儀しました。
計算サイトはたくさんあるので使えばいいのですが、せっかくなので自分でも計算ツールを作りました。
IPアドレス概要(今回の記事に関わる部分だけの超簡易版)
※注意※
CIDR計算ツールを作ることを主眼に置いているため、IPやネットワークの説明としてはあまり適切でない可能性があります。
IPアドレスを A.B.C.D/E とすると、
A~D:第1~第4オクテット
8bitごとに区切られ、各オクテットは 0 ~ 255 の範囲になります。E:サブネットマスク
ネットワークの区切り方を示すもので、値は 0 ~ 32 の範囲です。
何bit目までがマスクされるかを表していて、ネットワーク関係の設定では、255.255.255.0のような形で表記されます。
計算方法について
計算にはサブネットマスクを利用します。
サブネットマスクが 1 ~ 8 、9 ~ 16、17 ~ 24、25 ~ 32 のとき、それぞれ、第1、第2、第3、第4オクテットが計算の対象になります。
※サブネットマスクが 0 の場合はネットワークが区切られないため、計算の必要がありません。
先ほどの例(10.0.0.50/28)の場合、
32-28=4が、サブネットマスクされない残りのbit数であり、
2**4=16が、そのネットワークの中で設定可能なIPの個数となります。
その個数ずつ(=16個ずつ)に、オクテット全体が区切られています。
50は16個ずつ区切りの何番目か計算することで、IPアドレスの範囲を求めることができます。
また、10.0.42.0/22 の場合、
32-22=10が、サブネットマスクされない残りのbit数ですが、
24-22=2が、そのオクテットの中での残りのbit数となり、
2**2=4が、そのオクテットの中で設定可能な値の個数となります。
その個数ずつ(=4個ずつ)に、オクテット全体が区切られています。
42は4個ずつ区切りの何番目か計算することで、IPアドレスの範囲を求めることができます。
CIDR計算ツール
使用言語はPythonです。
import sys
def user_input():
# CIDRを計算したいIPアドレスを入力
print("IPアドレスを入力してください。 ex) 192.168.1.1/32")
input_ip_addr = input()
# 入力値を各オクテット、サブネットマスクに分割
sep_input = input_ip_addr.split("/")
ip_addr = sep_input[0]
ip_addr_sep = ip_addr.split(".")
octets = []
for i in range(0, 4):
octets.append(int(ip_addr_sep[i]))
subnet_mask = int(sep_input[1])
# 入力値の点検
check = "true"
for i in range(0, 4):
if octets[i] < 0 or octets[i] > 255:
print("IPアドレスの値が不適切です。")
check = "false"
if subnet_mask < 0 or subnet_mask > 32:
print("サブネットマスクの値が不適切です。")
check = "false"
if check == "false":
sys.exit()
# 必要な値を返す
return subnet_mask, octets
def calc_octet(octets, subnet_mask, oct_num):
# サブネットマスクの値から、区切られたネットワーク内でのIPの個数を計算
check_mask = 2 ** ( ( 8 * oct_num ) - subnet_mask )
# 当該オクテットの値が、サブネットマスクによって区切られたネットワークのうち、何番目に含まれるのか計算
steps = divmod(octets[oct_num - 1], check_mask)[0]
# 当該オクテットでのIPアドレス範囲を計算
oct_start = check_mask * steps
oct_end = check_mask * ( steps + 1 ) - 1
# 必要な値を返す
return oct_start, oct_end
def main(subnet_mask, octets):
# サブネットマスクが0(=ネットワークを区切らない)の場合
if subnet_mask == 0:
print(f"IPアドレス範囲は、0.0.0.0 から 255.255.255.255")
# サブネットマスク範囲が第1オクテットの場合
if 1 <= subnet_mask <= 8:
oct_num = int(1)
start_and_end = calc_octet(octets, subnet_mask, oct_num)
print(f"IPアドレス範囲は、{start_and_end[0]}.0.0.0 から {start_and_end[1]}.255.255.255")
# サブネットマスク範囲が第2オクテットの場合
if 9 <= subnet_mask <= 16:
oct_num = int(2)
start_and_end = calc_octet(octets, subnet_mask, oct_num)
ip_prefix = str(octets[0])
print(f"IPアドレス範囲は、{ip_prefix}.{start_and_end[0]}.0.0 から {ip_prefix}.{start_and_end[1]}.255.255")
# サブネットマスク範囲が第3オクテットの場合
if 17 <= subnet_mask <= 24:
oct_num = int(3)
start_and_end = calc_octet(octets, subnet_mask, oct_num)
ip_prefix = str(octets[0]) + "." + str(octets[1])
print(f"IPアドレス範囲は、{ip_prefix}.{start_and_end[0]}.0 から {ip_prefix}.{start_and_end[1]}.255")
# サブネットマスク範囲が第4オクテットの場合
if 25 <= subnet_mask <= 32:
oct_num = int(4)
start_and_end = calc_octet(octets, subnet_mask, oct_num)
ip_prefix = str(octets[0]) + "." + str(octets[1]) + "." + str(octets[2])
print(f"IPアドレス範囲は、{ip_prefix}.{start_and_end[0]} から {ip_prefix}.{start_and_end[1]}")
if __name__ == "__main__":
# CIDRを計算したいIPアドレスを入力
user_input = user_input()
# 入力値の処理結果を変数に格納
subnet_mask = user_input[0]
octets = user_input[1]
# IPアドレス範囲を計算
main(subnet_mask, octets)
ツール実行結果
例として挙げた2つを実際に計算してみます。
IPアドレスを入力してください。 ex) 192.168.1.1/32
10.0.0.50/28
IPアドレス範囲は、10.0.0.48 から 10.0.0.63
IPアドレスを入力してください。 ex) 192.168.1.1/32
10.0.42.0/22
IPアドレス範囲は、10.0.40.0 から 10.0.43.255
また、ほかのオクテットが対象になる場合なども確認してみます。
IPアドレスを入力してください。 ex) 192.168.1.1/32
10.10.20.20/12
IPアドレス範囲は、10.0.0.0 から 10.15.255.255
IPアドレスを入力してください。 ex) 192.168.1.1/32
10.10.10.10/5
IPアドレス範囲は、8.0.0.0 から 15.255.255.255
IPアドレスを入力してください。 ex) 192.168.1.1/32
10.200.0.0/0
IPアドレス範囲は、0.0.0.0 から 255.255.255.255
インターネットに公開されている計算サイトでの結果と比べてみましたが、問題なく計算できているようです。
余談
Pythonを使うなら、ipaddressモジュールがあるので、わざわざ自前の計算方法を組む必要はない、ということは、後で知りました…
この記事が気に入ったらサポートをしてみませんか?