代码之家  ›  专栏  ›  技术社区  ›  Josh K

验证IP地址(带掩码)

  •  11
  • Josh K  · 技术社区  · 14 年前

    我有ip地址和一个掩码,比如 10.1.1.1/32 . 我想看看 10.1.1.1 在这个范围内。是否有图书馆或实用程序可以做到这一点,或者我需要自己写一些东西?

    6 回复  |  直到 14 年前
        1
  •  28
  •   John Kugelman Michael Hodel    11 年前

    首先你要把你的IP地址转换成平面的 int s、 使用起来更容易:

    String       s = "10.1.1.99";
    Inet4Address a = (Inet4Address) InetAddress.getByName(s);
    byte[]       b = a.getAddress();
    int          i = ((b[0] & 0xFF) << 24) |
                     ((b[1] & 0xFF) << 16) |
                     ((b[2] & 0xFF) << 8)  |
                     ((b[3] & 0xFF) << 0);
    

    一旦你的IP地址是普通的 内景 您可以做一些位运算来执行检查:

    int subnet = 0x0A010100;   // 10.1.1.0/24
    int bits   = 24;
    int ip     = 0x0A010199;   // 10.1.1.99
    
    // Create bitmask to clear out irrelevant bits. For 10.1.1.0/24 this is
    // 0xFFFFFF00 -- the first 24 bits are 1's, the last 8 are 0's.
    //
    //     -1        == 0xFFFFFFFF
    //     32 - bits == 8
    //     -1 << 8   == 0xFFFFFF00
    mask = -1 << (32 - bits)
    
    if ((subnet & mask) == (ip & mask)) {
        // IP address is in the subnet.
    }
    
        2
  •  3
  •   mtk    12 年前
    public static boolean netMatch(String addr, String addr1){ //addr is subnet address and addr1 is ip address. Function will return true, if addr1 is within addr(subnet)
    
            String[] parts = addr.split("/");
            String ip = parts[0];
            int prefix;
    
            if (parts.length < 2) {
                prefix = 0;
            } else {
                prefix = Integer.parseInt(parts[1]);
            }
    
            Inet4Address a =null;
            Inet4Address a1 =null;
            try {
                a = (Inet4Address) InetAddress.getByName(ip);
                a1 = (Inet4Address) InetAddress.getByName(addr1);
            } catch (UnknownHostException e){}
    
            byte[] b = a.getAddress();
            int ipInt = ((b[0] & 0xFF) << 24) |
                             ((b[1] & 0xFF) << 16) |
                             ((b[2] & 0xFF) << 8)  |
                             ((b[3] & 0xFF) << 0);
    
            byte[] b1 = a1.getAddress();
            int ipInt1 = ((b1[0] & 0xFF) << 24) |
                             ((b1[1] & 0xFF) << 16) |
                             ((b1[2] & 0xFF) << 8)  |
                             ((b1[3] & 0xFF) << 0);
    
            int mask = ~((1 << (32 - prefix)) - 1);
    
            if ((ipInt & mask) == (ipInt1 & mask)) {
                return true;
            }
            else {
                return false;
            }
    }
    
        3
  •  3
  •   Carsten    10 年前

    下面是一个以几种常见方式接受子网描述的版本,包括 IPv6协议 .

    基于这里发布的其他代码。 打开 IPv4协议 地址它可能比在裸机上执行二进制操作的方法工作得慢 int 的。

    package de.c3oe.tryanderror;
    import java.math.BigInteger;
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    /**
     * @author c3oe.de, based on snippets from Scott Plante, John Kugelmann
     */
    public class Subnet
    {
        final private int bytesSubnetCount;
        final private BigInteger bigMask;
        final private BigInteger bigSubnetMasked;
    
        /** For use via format "192.168.0.0/24" or "2001:db8:85a3:880:0:0:0:0/57" */
        public Subnet( final InetAddress subnetAddress, final int bits )
        {
            this.bytesSubnetCount = subnetAddress.getAddress().length; // 4 or 16
            this.bigMask = BigInteger.valueOf( -1 ).shiftLeft( this.bytesSubnetCount*8 - bits ); // mask = -1 << 32 - bits
            this.bigSubnetMasked = new BigInteger( subnetAddress.getAddress() ).and( this.bigMask );
        }
    
        /** For use via format "192.168.0.0/255.255.255.0" or single address */
        public Subnet( final InetAddress subnetAddress, final InetAddress mask )
        {
            this.bytesSubnetCount = subnetAddress.getAddress().length;
            this.bigMask = null == mask ? BigInteger.valueOf( -1 ) : new BigInteger( mask.getAddress() ); // no mask given case is handled here.
            this.bigSubnetMasked = new BigInteger( subnetAddress.getAddress() ).and( this.bigMask );
        }
    
        /**
         * Subnet factory method.
         * @param subnetMask format: "192.168.0.0/24" or "192.168.0.0/255.255.255.0"
         *      or single address or "2001:db8:85a3:880:0:0:0:0/57"
         * @return a new instance
         * @throws UnknownHostException thrown if unsupported subnet mask.
         */
        public static Subnet createInstance( final String subnetMask )
                throws UnknownHostException
        {
            final String[] stringArr = subnetMask.split("/");
            if ( 2 > stringArr.length )
                return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), (InetAddress)null );
            else if ( stringArr[ 1 ].contains(".") || stringArr[ 1 ].contains(":") )
                return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), InetAddress.getByName( stringArr[ 1 ] ) );
            else
                return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), Integer.parseInt( stringArr[ 1 ] ) );
        }
    
        public boolean isInNet( final InetAddress address )
        {
            final byte[] bytesAddress = address.getAddress();
            if ( this.bytesSubnetCount != bytesAddress.length )
                return false;
            final BigInteger bigAddress = new BigInteger( bytesAddress );
            return  bigAddress.and( this.bigMask ).equals( this.bigSubnetMasked );
        }
    
        @Override
        final public boolean equals( Object obj )
        {
            if ( ! (obj instanceof Subnet) )
                return false;
            final Subnet other = (Subnet)obj;
            return  this.bigSubnetMasked.equals( other.bigSubnetMasked ) &&
                    this.bigMask.equals( other.bigMask ) &&
                    this.bytesSubnetCount == other.bytesSubnetCount;
        }
    
        @Override
        final public int hashCode()
        {
            return this.bytesSubnetCount;
        }
    
        @Override
        public String toString()
        {
            final StringBuilder buf = new StringBuilder();
            bigInteger2IpString( buf, this.bigSubnetMasked, this.bytesSubnetCount );
            buf.append( '/' );
            bigInteger2IpString( buf, this.bigMask, this.bytesSubnetCount );
            return buf.toString();
        }
    
        static private void bigInteger2IpString( final StringBuilder buf, final BigInteger bigInteger, final int displayBytes )
        {
            final boolean isIPv4 = 4 == displayBytes;
            byte[] bytes = bigInteger.toByteArray();
            int diffLen = displayBytes - bytes.length;
            final byte fillByte = 0 > (int)bytes[ 0 ] ? (byte)0xFF : (byte)0x00;
    
            int integer;
            for ( int i = 0; i < displayBytes; i++ )
            {
                if ( 0 < i && ! isIPv4 && i % 2 == 0 )
                    buf.append( ':' );
                else if ( 0 < i && isIPv4 )
                    buf.append( '.' );
                integer = 0xFF & (i < diffLen ? fillByte : bytes[ i - diffLen ]);
                if ( ! isIPv4 && 0x10 > integer )
                    buf.append( '0' );
                buf.append( isIPv4 ? integer : Integer.toHexString( integer ) );
            }
        }
    }
    
        4
  •  2
  •   Sean F    5 年前

    这只是几行代码 open-source IPAddress Java library . 免责声明:我是IPAddress库的项目经理。

    String subnetStr = "10.1.1.1/24";
    String addrStr = "10.1.1.1";
    IPAddress subnetAddress = new IPAddressString(subnetStr).getAddress();
    IPAddress subnet = subnetAddress.toPrefixBlock();
    IPAddress testAddress = new IPAddressString(addrStr).getAddress();
    boolean result = subnet.contains(testAddress);
    System.out.println(subnetAddress + " is in subnet " + subnet + " and " +
                (result ? "contains" : "does not contain") + " address " + testAddress);
    

    输出:

    10.1.1.1/24 is in subnet 10.1.1.0/24 and contains address 10.1.1.1
    
        5
  •  1
  •   Scott Plante    13 年前

    感谢John Kugelman——我用他的代码片段创建了这个类。

    package bs;
    
    import java.net.Inet4Address;
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    /**
     * Represents an IP range based on an address/mask.
     * @author Scott Plante, using code snippets by John Kugelman.
     */
    public class IPMask
    {
      public static void main(String args[]) 
          throws UnknownHostException
      {
        IPMask ipmask;
    
        ipmask = IPMask.getIPMask("192.168.20.32/24");
        System.out.println("Checking "+ipmask+"...");
    
        test(ipmask, "192.168.20.31 ", true);
        test(ipmask, "192.168.20.32 ", true);
        test(ipmask, "192.168.20.33 ", true);
        test(ipmask, "192.168.20.34 ", true);
        test(ipmask, "192.168.20.35 ", true);
        test(ipmask, "192.168.20.36 ", true);
        test(ipmask, "192.168.20.254", true);
        test(ipmask, "192.168.20.157", true);
        test(ipmask, "192.168.21.1  ", false);
        test(ipmask, "192.168.19.255", false);
        test(ipmask, "192.168.24.1  ", false);
    
        ipmask = IPMask.getIPMask("192.168.20.32/31");
        System.out.println("Checking "+ipmask+"...");
    
        test(ipmask, "192.168.20.31 ", false);
        test(ipmask, "192.168.20.32 ", true);
        test(ipmask, "192.168.20.33 ", true);
        test(ipmask, "192.168.20.34 ", false);
        test(ipmask, "192.168.20.35 ", false);
        test(ipmask, "192.168.20.36 ", false);
        test(ipmask, "192.168.20.254", false);
        test(ipmask, "192.168.20.157", false);
        test(ipmask, "192.168.21.1  ", false);
        test(ipmask, "192.168.19.255", false);
        test(ipmask, "192.168.24.1  ", false);
    
        ipmask = IPMask.getIPMask("192.168.20.32/23");
        System.out.println("Checking "+ipmask+"...");
    
        test(ipmask, "192.168.20.31 ", true);
        test(ipmask, "192.168.20.32 ", true);
        test(ipmask, "192.168.20.33 ", true);
        test(ipmask, "192.168.20.254", true);
        test(ipmask, "192.168.21.254", true);
        test(ipmask, "192.168.19.255", false);
        test(ipmask, "192.168.24.1  ", false);
    
      }
    
      public static void test(IPMask ipmask, String addr, boolean expect) 
          throws UnknownHostException
      {
        boolean got = ipmask.matches(addr);
        System.out.println(addr + "\t(" + expect + ") ?\t"+got
            + "\t" + (got==expect?"":"!!!!!!!!"));
      }
    
      private Inet4Address i4addr;
      private byte maskCtr;
    
      private int addrInt;
      private int maskInt;
    
      public IPMask(Inet4Address i4addr, byte mask)
      {
        this.i4addr = i4addr;
        this.maskCtr = mask;
    
        this.addrInt = addrToInt(i4addr);
        this.maskInt = ~((1 << (32 - maskCtr)) - 1);
      }
    
      /** IPMask factory method. 
       * 
       * @param addrSlashMask IP/Mask String in format "nnn.nnn.nnn.nnn/mask". If 
       *    the "/mask" is omitted, "/32" (just the single address) is assumed.
       * @return a new IPMask
       * @throws UnknownHostException if address part cannot be parsed by 
       *    InetAddress
       */
      public static IPMask getIPMask(String addrSlashMask) 
          throws UnknownHostException
      {
        int pos = addrSlashMask.indexOf('/');
        String addr;
        byte maskCtr;
        if (pos==-1)
        {
          addr = addrSlashMask;
          maskCtr = 32;
        }
        else
        { 
          addr = addrSlashMask.substring(0, pos);
          maskCtr = Byte.parseByte(addrSlashMask.substring(pos + 1));
        }
        return new IPMask((Inet4Address) InetAddress.getByName(addr), maskCtr);
      }
    
     /** Test given IPv4 address against this IPMask object.
       * 
       * @param testAddr address to check.
       * @return true if address is in the IP Mask range, false if not.
       */  
      public boolean matches(Inet4Address testAddr)
      {
        int testAddrInt = addrToInt(testAddr);   
        return ((addrInt & maskInt) == (testAddrInt & maskInt));
      }
    
    /** Convenience method that converts String host to IPv4 address.
       * 
       * @param addr IP address to match in nnn.nnn.nnn.nnn format or hostname.
       * @return true if address is in the IP Mask range, false if not.
       * @throws UnknownHostException if the string cannot be decoded.
       */
      public boolean matches(String addr) 
          throws UnknownHostException
      {
        return matches((Inet4Address)InetAddress.getByName(addr));
      }
    
    /** Converts IPv4 address to integer representation.
       */
      private static int addrToInt(Inet4Address i4addr)
      {
        byte[] ba = i4addr.getAddress();  
        return (ba[0]       << 24) 
            | ((ba[1]&0xFF) << 16) 
            | ((ba[2]&0xFF) << 8) 
            |  (ba[3]&0xFF);
      }
    
      @Override
      public String toString()
      {
        return "IPMask(" + i4addr.getHostAddress() + "/" + maskCtr + ")";
      }
    
      @Override
      public boolean equals(Object obj)
      {
        if (obj == null)
          return false;
        if (getClass() != obj.getClass())
          return false;
        final IPMask that = (IPMask) obj;    
        return (this.addrInt == that.addrInt && this.maskInt == that.maskInt);
      }
    
      @Override
      public int hashCode()
      {
        return this.maskInt + this.addrInt;
      }
    
    }
    

    我确实需要在他的代码中为int转换添加一个掩码:

    Inet4Address a = (Inet4Address) InetAddress.getByName("192.192.192.192");
    byte[]       b = a.getAddress();
    int          i = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0);
    System.out.println(Integer.toHexString(i));
    System.out.println(Integer.toHexString(addrToInt(a)));
    

    产生:

    ffffffc0
    c0c0c0c0
    

    在我的系统上:

    $> uname -a
    Linux guin 2.6.37.6-0.5-desktop #1 SMP PREEMPT 2011-04-25 21:48:33 +0200 x86_64 x86_64 x86_64 GNU/Linux
    $> java -version
    java version "1.6.0_25"
    Java(TM) SE Runtime Environment (build 1.6.0_25-b06)
    Java HotSpot(TM) 64-Bit Server VM (build 20.0-b11, mixed mode)
    $> 
    

    可以从上述类中删除main和test方法。它们改编自单元测试代码,为了简单起见添加在这里。

        6
  •  1
  •   djpanda    5 年前

    commons-ip-math 我相信图书馆做得很好。请注意,截至2019年5月,图书馆已有2年没有任何更新(可能是它已经非常成熟的图书馆)。它在上可用 maven-central

    它支持同时使用IPv4和IPv6地址。他们的简要文档中有一些示例,说明如何检查地址是否在 IPv4 IPv6

    IPv4范围检查示例:

            String input1 = "10.1.1.1";
            Ipv4 ipv41 = Ipv4.parse(input1);
    
            // Using CIDR notation to specify the networkID and netmask
            Ipv4Range range = Ipv4Range.parse("10.1.1.1/32");
            boolean result = range.contains(ipv41);
            System.out.println(result); //true
    
            String input2 = "10.1.1.1";
            Ipv4 ipv42 = Ipv4.parse(input2);
    
            // Specifying the range with a start and end.
            Ipv4 start = Ipv4.of("10.1.1.1");
            Ipv4 end = Ipv4.of("10.1.1.1");
            range = Ipv4Range.from(start).to(end);
    
            result = range.contains(ipv42); //true
            System.out.println(result);