IPアドレスの範囲チェックを行う(Java)

IPアドレスの範囲チェックのサンプルを探してみたら Apache James 等のライブラリを使用する例しか見つからなかったので、 スクラッチで組んでみたらどうなるかやってみた。

チェッククラス

package example;

public class CheckIpAddress {

	/**
	 * IPアドレスがプライベートIPかどうかをチェックする。<br />
	 * @param checkIp チェックするIPアドレス
	 * @return true:プライベートIP、false:プライベートIPではない
	 */
	public static boolean isPrivateIpAddres(String checkIp){

		if (chekRangeIpAddress(checkIp, "10.0.0.0", "10.255.255.255")
		||  chekRangeIpAddress(checkIp, "172.16.0.0", "172.31.255.255")
		||  chekRangeIpAddress(checkIp, "192.168.0.0", "192.168.255.255")){
			return true;
		}
		return false;
	}

	/**
	 * IPアドレスが指定された範囲ないかどうかをチェックする。<br />
	 * @param checkIp チェックするIPアドレス
	 * @param firstIp 先頭IPアドレス
	 * @param lastIp  最終IPアドレス
	 * @return true:範囲内、false:範囲外
	 */
	public static boolean chekRangeIpAddress(String checkIp, String firstIp, String lastIp){

		// 桁数揃え
		checkIp = formatIp(checkIp);
		firstIp = formatIp(firstIp);
		lastIp  = formatIp(lastIp);

		// 整形できない場合はエラー
		if (checkIp == null || firstIp == null || lastIp == null) {
			return false;
		}
		
		// 範囲内かチェック
		if (checkIp.compareTo(firstIp) < 0 || checkIp.compareTo(lastIp) > 0) {
			return false;
		}

		return true;
	}

	/**
	 * IPアドレスの桁数を揃える(各セグメントを3桁に揃える)
	 * @param ip IPアドレス
	 * @return 整形後のIPアドレス
	 */
	public static String formatIp(String ip){

		// 4つに分割できない時はエラー
		String[] ipArray = ip.split("\\.");
		if (ipArray.length != 4) {
			return null;
		} 

		// 数値とピリオド以外にマッチした場合はエラー
		for (int i = 0; i < 4; i++) {
			String ipPart = ipArray[i];
			if (ipPart == null || ipPart.isEmpty() || (ipPart.matches("[^0-9]"))){
				return null;
			} 
		} 
		
		// 3桁に満たない場合は3桁にする
		for (int i = 0; i < 4; i++){
			int len = ipArray[i].length();
			for (int j = len; j < 3; j++) {
				ipArray[i] = "0" + ipArray[i];
			} 
		} 

		// 3桁*4のIPを組立
		String delimiter = "";
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < 4; i++){
			sb.append(delimiter);
			sb.append(ipArray[i]);
			delimiter = ".";
		} 
		return sb.toString();
	} 
} 

確認用コード

※ 注意)環境にもよると思うが、全IPをチェックしようと思ったら8時間ぐらいかかる。

package example;

import java.util.Date;

public class CopyOfCheckIpAddressTest {

	// 個別チェック用
	//public static void main(String[] args) {
	//	
	//	boolean res = CheckIpAddress.chekRangeIpAddress("172.30.255.255", "172.30.200.255", "172.31.200.255");
	//	System.out.println(res);
	//}

	public static void main(String[] args) {

		System.out.println("Start ... " + new Date());

		long[] result0 = checkPrivateIp("0.0.0.0"     , "9.255.255.255"   , false); //
		long[] result1 = checkPrivateIp("10.0.0.0"    , "10.255.255.255"  , true);  // クラスA
		long[] result2 = checkPrivateIp("11.0.0.0"    , "171.255.255.255" , false); //
		long[] result3 = checkPrivateIp("172.16.0.0"  , "172.31.255.255"  , true);  // クラスB
		long[] result4 = checkPrivateIp("172.32.0.0"  , "192.167.255.255" , false); //
		long[] result5 = checkPrivateIp("192.168.0.0" , "192.168.255.255" , true);  // クラスC
		long[] result6 = checkPrivateIp("192.169.0.0" , "255.255.255.255" , false); //
		long okCntAll = result0[0] + result1[0] + result2[0] + result3[0] + result4[0] + result5[0] + result6[0];
		long ngCntAll = result0[1] + result1[1] + result2[1] + result3[1] + result4[1] + result5[1] + result6[1];

		System.out.println("チェック件数 : " + (okCntAll + ngCntAll));
		System.out.println("正常件数    : " + okCntAll);
		System.out.println("エラー件数   : " + ngCntAll);
		
		if (ngCntAll == 0) {
			System.out.println("エラーなし");
		} else {
			System.err.println("エラーあり!!!");
		}
		System.out.println("End   ... " + new Date());
	}

	/**
	 * プライベートIPアドレスかどうかをチェックする
	 * @param fstIp  チェックするIPの開始値
	 * @param lastIp チェックするIPの最終値
	 * @param expected 期待値(true:プライベートIP)
	 * @return [チェックOK件数、チェックエラー件数]
	 */
	private static long[] checkPrivateIp(String fstIp, String lastIp, boolean expected){

		System.out.println("チェック開始 : " + fstIp + " - " + lastIp);
		
		String[] fstIpAry  = fstIp.split("\\.");
		String[] lastIpAry = lastIp.split("\\.");
		if ((fstIpAry.length != 4) || (lastIpAry.length != 4)) {
			throw new RuntimeException("引数が誤っています(" + fstIp + "," + lastIp + ")");
		}

		long okCnt = 0;
		long ngCnt = 0;
		String checkIp = fstIp;
		while (ipCompareTo(checkIp, lastIp) <= 0) {
			boolean result = CheckIpAddress.isPrivateIpAddres(checkIp);
			if (result == expected) {
				okCnt++;
				//System.out.println("期待値する結果です\t" + checkIp + "\t期待値:" + expected + "\t結果:" + result );
			} else {
				ngCnt++;
				System.err.println("期待値と異なります!\t" + checkIp + "\t期待値:" + expected + "\t結果:" + result );
			}
			checkIp = nextIp(checkIp);
		}
		System.out.println("チェック終了 : " + fstIp + " - " + lastIp);
		
		return new long[]{okCnt, ngCnt};
	}

	/**
	 * IPアドレスの大小比較
	 * @param checkIp   IPアドレス1
	 * @param compareIp IPアドレス2
	 * @return 比較結果
	 */
	private static int ipCompareTo(String checkIp, String compareIp){
		checkIp = CheckIpAddress.formatIp(checkIp);
		compareIp = CheckIpAddress.formatIp(compareIp);
		return checkIp.compareTo(compareIp);
	}

	/**
	 * 次のIPアドレスを取得する。
	 * @param checkIp IPアドレス
	 * @return 次のIPアドレス
	 */
	private static String nextIp(String ip){

		String[] ipArray = ip.split("\\.");
		for (int i = 3; i >= 0; i--) {
			int ipPart = Integer.parseInt(ipArray[i]);
			if (ipPart < 255){
				ipArray[i] = String.valueOf(++ipPart);
				return ipArray[0] + "." + ipArray[1] + "." + ipArray[2] + "." + ipArray[3];
			} else {
				ipArray[i] = "0";
			} 
		} 
		return "255.255.255.256";
	} 

} 

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-05-22 (日) 04:50:10 (932d)