IP アドレス操作ライブラリ IPAddress

IPAddress は、IPv4 や IPv6 の IP アドレスに対する様々な操作が可能なライブラリ。

Java の実装と Go の実装が提供されている。

seancfoley.github.io

簡単に使用方法を見ておく。


導入

Gradle の場合は以下。

implementation("com.github.seancfoley:ipaddress:5.5.0")

Maven の場合は以下。

<dependency>
    <groupId>com.github.seancfoley</groupId>
    <artifactId>ipaddress</artifactId>
    <version>5.5.0</version>
</dependency>


IPAddress

IPAddressString から toAddress()IPAddress を取得。

IPAddressString str = new IPAddressString("1.2.3.4");
try {
    IPAddress ip = str.toAddress();
    System.out.println(ip); // 1.2.3.4
} catch (AddressStringException e) { ... }

getAddress() を使うと、パース失敗時には例外とならず、null となるので、以下のように使用できる。

var addr = Optional.ofNullable(new IPAddressString("1.2.3.4").getAddress());


ホスト名

ポート番号含むホスト名の場合は以下のようにできる。

HostName host = new HostName("1.2.3.4:80");  
InetSocketAddress sa = host.asInetSocketAddress();  
System.out.println(sa); // /1.2.3.4:80


IP アドレスの解釈

以下のようにパースされるので注意が必要。

System.out.println(new IPAddressString(null).getAddress());        // 127.0.0.1
System.out.println(new IPAddressString("").getAddress());          // 127.0.0.1
System.out.println(new IPAddressString("1").getAddress());         // 0.0.0.1
System.out.println(new IPAddressString("1.").getAddress());        // null
System.out.println(new IPAddressString("1.2").getAddress());       // 1.0.0.2
System.out.println(new IPAddressString("1.2.").getAddress());      // null
System.out.println(new IPAddressString("1.2.3").getAddress());     // 1.2.0.3
System.out.println(new IPAddressString("1.2.3.").getAddress());    // null
System.out.println(new IPAddressString("1.2.3.4").getAddress());   // 1.2.3.4
System.out.println(new IPAddressString("1.2.3.4.").getAddress());  // null
System.out.println(new IPAddressString("1.2.3.4.5").getAddress()); // null

空の文字列はデフォルトのループバックとみなされる。

1.2 のような解釈は、BSD Unix の inet_atonユーティリティの IPv4 文字列形式で、これを無効にする場合は以下のようにする。

var params = new IPAddressStringParameters.Builder()
        .allow_inet_aton(false)
        .toParams();  
System.out.println(new IPAddressString("1.2", params).getAddress()); // null


CIDR Address

1.2.0.0/16, 1.2.0.0/255.255.0.0, 1.2.*.*, 1.2.0-255.0-255, のような指定でサブネット指定できる。

IPAddress ip = new IPAddressString("1.2.3.0/24").getAddress();  
System.out.println(ip);                                    // 1.2.3.0/24  
System.out.println(ip.getIPVersion());                     // IPv4  
System.out.println(Arrays.deepToString(ip.getSegments())); // [1, 2, 3, 0-255]  
System.out.println(ip.getBitCount());                      // 32  
System.out.println(ip.getCount());                         // 256  
System.out.println(ip.getNetworkPrefixLength());           // 24  
System.out.println(ip.getNetworkMask());                   // 255.255.255.0/24

ただし、以下の場合はサブネットとして解釈されず、個別の 1.2.3.4 として解釈されるので注意が必要

IPAddress ip = new IPAddressString("1.2.3.4/24").getAddress();  
System.out.println(ip);                                    // 1.2.3.0/24  
System.out.println(ip.getIPVersion());                     // IPv4  
System.out.println(Arrays.deepToString(ip.getSegments())); // [1, 2, 3, 4]  
System.out.println(ip.getBitCount());                      // 32  
System.out.println(ip.getCount());                         // 1  
System.out.println(ip.getNetworkPrefixLength());           // 24  
System.out.println(ip.getNetworkMask());                   // 255.255.255.0/24

すなわち以下となる。

System.out.println(new IPAddressString("1.2.3.0/24").getAddress()  
        .contains(new IPAddressString("1.2.3.4").getAddress()));  // true  
  
System.out.println(new IPAddressString("1.2.3.4/24").getAddress()  
        .contains(new IPAddressString("1.2.3.4").getAddress()));  // true  
  
System.out.println(new IPAddressString("1.2.3.4/24").getAddress()  
        .contains(new IPAddressString("1.2.3.5").getAddress()));  // false

toPrefixBlock() を使うと以下のように包含をチェックできる。

System.out.println(new IPAddressString("1.2.3.0/24").getAddress().toPrefixBlock()
        .contains(new IPAddressString("1.2.3.4").getAddress()));  // true

System.out.println(new IPAddressString("1.2.3.4/24").getAddress().toPrefixBlock()
        .contains(new IPAddressString("1.2.3.4").getAddress()));  // true

System.out.println(new IPAddressString("1.2.3.4/24").getAddress().toPrefixBlock()
        .contains(new IPAddressString("1.2.3.5").getAddress()));  // true


IPv6 IPAddress

IPv6 正規、圧縮(1::1)、混合(1:2:3:4:5:6:1.2.3.4)、形式で指定できる。

System.out.println(new IPAddressString("1:2:3:0:0:6::").getAddress());   // 1:2:3::6:0:0
System.out.println(new IPAddressString("1:2:3:0:0:6:0:0").getAddress()); // 1:2:3::6:0:0
System.out.println(new IPAddressString("1:2:3::6:0:0").getAddress());    // 1:2:3::6:0:0
System.out.println(new IPAddressString("0001:0002:0003:0000:0000:0006:0000:0000").getAddress()); // 1:2:3::6:0:0

サブネットに関してもIPv4と同様に指定できる

System.out.println(new IPAddressString("ffff::/104").getAddress());             // ffff::/104
System.out.println(new IPAddressString("ffff:0:0:0:0:0:0:0/104").getAddress()); // ffff::/104