You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2019/03/07 12:15:33 UTC

[incubator-dubbo] branch master updated: Merge pull request #3578, fixes #3289, enhance tagRoute: support ip expression match.

This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git


The following commit(s) were added to refs/heads/master by this push:
     new 172d694  Merge pull request #3578, fixes #3289, enhance tagRoute:  support ip expression match.
172d694 is described below

commit 172d69472fab2049ff0e7f019efcfe77c4378c27
Author: cvictory <sh...@gmail.com>
AuthorDate: Thu Mar 7 20:15:22 2019 +0800

    Merge pull request #3578, fixes #3289, enhance tagRoute:  support ip expression match.
---
 LICENSE                                            |   5 +
 .../router/condition/config/ListenableRouter.java  |   2 +-
 .../dubbo/rpc/cluster/router/tag/TagRouter.java    |  23 +++-
 .../org/apache/dubbo/common/utils/CIDRUtils.java   | 140 +++++++++++++++++++++
 .../org/apache/dubbo/common/utils/NetUtils.java    | 137 +++++++++++++++++++-
 .../apache/dubbo/common/utils/CIDRUtilsTest.java   |  56 +++++++++
 .../apache/dubbo/common/utils/NetUtilsTest.java    |  91 ++++++++++++++
 7 files changed, 448 insertions(+), 6 deletions(-)

diff --git a/LICENSE b/LICENSE
index a35e3b9..11eea3b 100644
--- a/LICENSE
+++ b/LICENSE
@@ -220,3 +220,8 @@ This product contains a modified portion of 'Netty', an event-driven asynchronou
  * io.netty.util.Timeout
  * io.netty.util.HashedWheelTimer
 
+For the org.apache.dubbo.common.utils.CIDRUtils :
+
+This product contains a modified portion of 'edazdarevic.commons.net.CIDRUtils',
+ under a "MIT License" license, see https://github.com/edazdarevic/CIDRUtils/blob/master/CIDRUtils.java
+
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ListenableRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ListenableRouter.java
index 913fd55..564f371 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ListenableRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ListenableRouter.java
@@ -120,7 +120,7 @@ public abstract class ListenableRouter extends AbstractRouter implements Configu
         String routerKey = ruleKey + RULE_SUFFIX;
         configuration.addListener(routerKey, this);
         String rule = configuration.getConfig(routerKey);
-        if (rule != null) {
+        if (StringUtils.isNotEmpty(rule)) {
             this.process(new ConfigChangeEvent(routerKey, rule));
         }
     }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
index 1bace4f..d03efca 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
@@ -21,6 +21,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.configcenter.ConfigChangeEvent;
 import org.apache.dubbo.configcenter.ConfigChangeType;
@@ -33,6 +34,7 @@ import org.apache.dubbo.rpc.cluster.router.AbstractRouter;
 import org.apache.dubbo.rpc.cluster.router.tag.model.TagRouterRule;
 import org.apache.dubbo.rpc.cluster.router.tag.model.TagRuleParser;
 
+import java.net.UnknownHostException;
 import java.util.List;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -196,11 +198,26 @@ public class TagRouter extends AbstractRouter implements ConfigurationListener {
     }
 
     private boolean addressMatches(URL url, List<String> addresses) {
-        return addresses != null && addresses.contains(url.getAddress());
+        return addresses != null && checkAddressMatch(addresses, url.getHost(), url.getPort());
     }
 
     private boolean addressNotMatches(URL url, List<String> addresses) {
-        return addresses == null || !addresses.contains(url.getAddress());
+        return addresses == null || !checkAddressMatch(addresses, url.getHost(), url.getPort());
+    }
+
+    private boolean checkAddressMatch(List<String> addresses, String host, int port) {
+        for (String address : addresses) {
+            try {
+                if (NetUtils.matchIpExpression(address, host, port)) {
+                    return true;
+                }
+            } catch (UnknownHostException e) {
+                logger.error("The format of ip address is invalid in tag route. Address :" + address, e);
+            } catch (Exception e) {
+                logger.error("The format of ip address is invalid in tag route. Address :" + address, e);
+            }
+        }
+        return false;
     }
 
     public void setApplication(String app) {
@@ -232,7 +249,7 @@ public class TagRouter extends AbstractRouter implements ConfigurationListener {
                 configuration.addListener(key, this);
                 application = providerApplication;
                 String rawRule = configuration.getConfig(key);
-                if (rawRule != null) {
+                if (StringUtils.isNotEmpty(rawRule)) {
                     this.process(new ConfigChangeEvent(key, rawRule));
                 }
             }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CIDRUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CIDRUtils.java
new file mode 100644
index 0000000..5d9dc8b
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CIDRUtils.java
@@ -0,0 +1,140 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2013 Edin Dazdarevic (edin.dazdarevic@gmail.com)
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **/
+package org.apache.dubbo.common.utils;
+
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A class that enables to get an IP range from CIDR specification. It supports
+ * both IPv4 and IPv6.
+ * <p>
+ * From https://github.com/edazdarevic/CIDRUtils/blob/master/CIDRUtils.java
+ */
+public class CIDRUtils {
+    private final String cidr;
+
+    private InetAddress inetAddress;
+    private InetAddress startAddress;
+    private InetAddress endAddress;
+    private final int prefixLength;
+
+
+    public CIDRUtils(String cidr) throws UnknownHostException {
+
+        this.cidr = cidr;
+
+        /* split CIDR to address and prefix part */
+        if (this.cidr.contains("/")) {
+            int index = this.cidr.indexOf("/");
+            String addressPart = this.cidr.substring(0, index);
+            String networkPart = this.cidr.substring(index + 1);
+
+            inetAddress = InetAddress.getByName(addressPart);
+            prefixLength = Integer.parseInt(networkPart);
+
+            calculate();
+        } else {
+            throw new IllegalArgumentException("not an valid CIDR format!");
+        }
+    }
+
+
+    private void calculate() throws UnknownHostException {
+
+        ByteBuffer maskBuffer;
+        int targetSize;
+        if (inetAddress.getAddress().length == 4) {
+            maskBuffer =
+                    ByteBuffer
+                            .allocate(4)
+                            .putInt(-1);
+            targetSize = 4;
+        } else {
+            maskBuffer = ByteBuffer.allocate(16)
+                    .putLong(-1L)
+                    .putLong(-1L);
+            targetSize = 16;
+        }
+
+        BigInteger mask = (new BigInteger(1, maskBuffer.array())).not().shiftRight(prefixLength);
+
+        ByteBuffer buffer = ByteBuffer.wrap(inetAddress.getAddress());
+        BigInteger ipVal = new BigInteger(1, buffer.array());
+
+        BigInteger startIp = ipVal.and(mask);
+        BigInteger endIp = startIp.add(mask.not());
+
+        byte[] startIpArr = toBytes(startIp.toByteArray(), targetSize);
+        byte[] endIpArr = toBytes(endIp.toByteArray(), targetSize);
+
+        this.startAddress = InetAddress.getByAddress(startIpArr);
+        this.endAddress = InetAddress.getByAddress(endIpArr);
+
+    }
+
+    private byte[] toBytes(byte[] array, int targetSize) {
+        int counter = 0;
+        List<Byte> newArr = new ArrayList<Byte>();
+        while (counter < targetSize && (array.length - 1 - counter >= 0)) {
+            newArr.add(0, array[array.length - 1 - counter]);
+            counter++;
+        }
+
+        int size = newArr.size();
+        for (int i = 0; i < (targetSize - size); i++) {
+
+            newArr.add(0, (byte) 0);
+        }
+
+        byte[] ret = new byte[newArr.size()];
+        for (int i = 0; i < newArr.size(); i++) {
+            ret[i] = newArr.get(i);
+        }
+        return ret;
+    }
+
+    public String getNetworkAddress() {
+
+        return this.startAddress.getHostAddress();
+    }
+
+    public String getBroadcastAddress() {
+        return this.endAddress.getHostAddress();
+    }
+
+    public boolean isInRange(String ipAddress) throws UnknownHostException {
+        InetAddress address = InetAddress.getByName(ipAddress);
+        BigInteger start = new BigInteger(1, this.startAddress.getAddress());
+        BigInteger end = new BigInteger(1, this.endAddress.getAddress());
+        BigInteger target = new BigInteger(1, address.getAddress());
+
+        int st = start.compareTo(target);
+        int te = target.compareTo(end);
+
+        return (st == -1 || st == 0) && (te == -1 || te == 0);
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java
index eae4574..91f04b8 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java
@@ -57,6 +57,9 @@ public class NetUtils {
     private static final Map<String, String> hostNameCache = new LRUCache<>(1000);
     private static volatile InetAddress LOCAL_ADDRESS = null;
 
+    private static final String SPLIT_IPV4_CHARECTER = "\\.";
+    private static final String SPLIT_IPV6_CHARECTER = ":";
+
     public static int getRandomPort() {
         return RND_PORT_START + ThreadLocalRandom.current().nextInt(RND_PORT_RANGE);
     }
@@ -340,13 +343,13 @@ public class NetUtils {
         return sb.toString();
     }
 
-    public static void joinMulticastGroup (MulticastSocket multicastSocket, InetAddress multicastAddress) throws IOException {
+    public static void joinMulticastGroup(MulticastSocket multicastSocket, InetAddress multicastAddress) throws IOException {
         setInterface(multicastSocket, multicastAddress instanceof Inet6Address);
         multicastSocket.setLoopbackMode(false);
         multicastSocket.joinGroup(multicastAddress);
     }
 
-    public static void setInterface (MulticastSocket multicastSocket, boolean preferIpv6) throws IOException{
+    public static void setInterface(MulticastSocket multicastSocket, boolean preferIpv6) throws IOException {
         boolean interfaceSet = false;
         Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
         while (interfaces.hasMoreElements()) {
@@ -370,4 +373,134 @@ public class NetUtils {
         }
     }
 
+    public static boolean matchIpExpression(String pattern, String host, int port) throws UnknownHostException {
+
+        // if the pattern is subnet format, it will not be allowed to config port param in pattern.
+        if (pattern.contains("/")) {
+            CIDRUtils utils = new CIDRUtils(pattern);
+            return utils.isInRange(host);
+        }
+
+
+        return matchIpRange(pattern, host, port);
+    }
+
+    /**
+     * @param pattern
+     * @param host
+     * @param port
+     * @return
+     * @throws UnknownHostException
+     */
+    public static boolean matchIpRange(String pattern, String host, int port) throws UnknownHostException {
+        if (pattern == null || host == null) {
+            throw new IllegalArgumentException("Illegal Argument pattern or hostName. Pattern:" + pattern + ", Host:" + host);
+        }
+        pattern = pattern.trim();
+        if (pattern.equals("*.*.*.*") || pattern.equals("*")) {
+            return true;
+        }
+
+        InetAddress inetAddress = InetAddress.getByName(host);
+        boolean isIpv4 = isValidV4Address(inetAddress) ? true : false;
+        String[] hostAndPort = getPatternHostAndPort(pattern, isIpv4);
+        if (hostAndPort[1] != null && !hostAndPort[1].equals(String.valueOf(port))) {
+            return false;
+        }
+        pattern = hostAndPort[0];
+
+        String splitCharacter = SPLIT_IPV4_CHARECTER;
+        if (!isIpv4) {
+            splitCharacter = SPLIT_IPV6_CHARECTER;
+        }
+        String[] mask = pattern.split(splitCharacter);
+        //check format of pattern
+        checkHostPattern(pattern, mask, isIpv4);
+
+        host = inetAddress.getHostAddress();
+
+        String[] ip_address = host.split(splitCharacter);
+        if (pattern.equals(host)) {
+            return true;
+        }
+        // short name condition
+        if (!ipPatternContainExpression(pattern)) {
+            InetAddress patternAddress = InetAddress.getByName(pattern);
+            if (patternAddress.getHostAddress().equals(host)) {
+                return true;
+            } else {
+                return false;
+            }
+        }
+        for (int i = 0; i < mask.length; i++) {
+            if (mask[i].equals("*") || mask[i].equals(ip_address[i])) {
+                continue;
+            } else if (mask[i].contains("-")) {
+                String[] rangeNumStrs = mask[i].split("-");
+                if (rangeNumStrs.length != 2) {
+                    throw new IllegalArgumentException("There is wrong format of ip Address: " + mask[i]);
+                }
+                Integer min = getNumOfIpSegment(rangeNumStrs[0], isIpv4);
+                Integer max = getNumOfIpSegment(rangeNumStrs[1], isIpv4);
+                Integer ip = getNumOfIpSegment(ip_address[i], isIpv4);
+                if (ip < min || ip > max) {
+                    return false;
+                }
+            } else if ("0".equals(ip_address[i]) && ("0".equals(mask[i]) || "00".equals(mask[i]) || "000".equals(mask[i]) || "0000".equals(mask[i]))) {
+                continue;
+            } else if (!mask[i].equals(ip_address[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static boolean ipPatternContainExpression(String pattern) {
+        return pattern.contains("*") || pattern.contains("-");
+    }
+
+    private static void checkHostPattern(String pattern, String[] mask, boolean isIpv4) {
+        if (!isIpv4) {
+            if (mask.length != 8 && ipPatternContainExpression(pattern)) {
+                throw new IllegalArgumentException("If you config ip expression that contains '*' or '-', please fill qulified ip pattern like 234e:0:4567:0:0:0:3d:*. ");
+            }
+            if (mask.length != 8 && !pattern.contains("::")) {
+                throw new IllegalArgumentException("The host is ipv6, but the pattern is not ipv6 pattern : " + pattern);
+            }
+        } else {
+            if (mask.length != 4) {
+                throw new IllegalArgumentException("The host is ipv4, but the pattern is not ipv4 pattern : " + pattern);
+            }
+        }
+    }
+
+    private static String[] getPatternHostAndPort(String pattern, boolean isIpv4) {
+        String[] result = new String[2];
+        if (pattern.startsWith("[") && pattern.contains("]:")) {
+            int end = pattern.indexOf("]:");
+            result[0] = pattern.substring(1, end);
+            result[1] = pattern.substring(end + 2);
+            return result;
+        } else if (pattern.startsWith("[") && pattern.endsWith("]")) {
+            result[0] = pattern.substring(1, pattern.length() - 1);
+            result[1] = null;
+            return result;
+        } else if (isIpv4 && pattern.contains(":")) {
+            int end = pattern.indexOf(":");
+            result[0] = pattern.substring(0, end);
+            result[1] = pattern.substring(end + 1);
+            return result;
+        } else {
+            result[0] = pattern;
+            return result;
+        }
+    }
+
+    private static Integer getNumOfIpSegment(String ipSegment, boolean isIpv4) {
+        if (isIpv4) {
+            return Integer.parseInt(ipSegment);
+        }
+        return Integer.parseInt(ipSegment, 16);
+    }
+
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CIDRUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CIDRUtilsTest.java
new file mode 100644
index 0000000..d0c627d
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CIDRUtilsTest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.utils;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.net.UnknownHostException;
+
+/**
+ * @author cvictory ON 2019-02-28
+ */
+public class CIDRUtilsTest {
+
+    @Test
+    public void testIpv4() throws UnknownHostException {
+        CIDRUtils cidrUtils = new CIDRUtils("192.168.1.0/26");
+        Assertions.assertTrue(cidrUtils.isInRange("192.168.1.63"));
+        Assertions.assertFalse(cidrUtils.isInRange("192.168.1.65"));
+
+        cidrUtils = new CIDRUtils("192.168.1.192/26");
+        Assertions.assertTrue(cidrUtils.isInRange("192.168.1.199"));
+        Assertions.assertFalse(cidrUtils.isInRange("192.168.1.190"));
+    }
+
+    @Test
+    public void testIpv6() throws UnknownHostException {
+        CIDRUtils cidrUtils = new CIDRUtils("234e:0:4567::3d/64");
+        Assertions.assertTrue(cidrUtils.isInRange("234e:0:4567::3e"));
+        Assertions.assertTrue(cidrUtils.isInRange("234e:0:4567::ffff:3e"));
+        Assertions.assertFalse(cidrUtils.isInRange("234e:1:4567::3d"));
+        Assertions.assertFalse(cidrUtils.isInRange("234e:0:4567:1::3d"));
+
+        cidrUtils = new CIDRUtils("3FFE:FFFF:0:CC00::/54");
+        Assertions.assertTrue(cidrUtils.isInRange("3FFE:FFFF:0:CC00::dd"));
+        Assertions.assertTrue(cidrUtils.isInRange("3FFE:FFFF:0:CC00:0000:eeee:0909:dd"));
+        Assertions.assertTrue(cidrUtils.isInRange("3FFE:FFFF:0:CC0F:0000:eeee:0909:dd"));
+
+        Assertions.assertFalse(cidrUtils.isInRange("3EFE:FFFE:0:C107::dd"));
+        Assertions.assertFalse(cidrUtils.isInRange("1FFE:FFFE:0:CC00::dd"));
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java
index d193fe0..2fe0a63 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java
@@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test;
 import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.equalTo;
@@ -32,6 +33,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -207,4 +209,93 @@ public class NetUtilsTest {
         InetAddress normalized = NetUtils.normalizeV6Address(address);
         assertThat(normalized.getHostAddress(), equalTo("fe80:0:0:0:894:aeec:f37d:23e1%5"));
     }
+
+    @Test
+    public void testMatchIpRangeMatchWhenIpv4() throws UnknownHostException {
+        assertTrue(NetUtils.matchIpRange("*.*.*.*", "192.168.1.63", 90));
+        assertTrue(NetUtils.matchIpRange("192.168.1.*", "192.168.1.63", 90));
+        assertTrue(NetUtils.matchIpRange("192.168.1.63", "192.168.1.63", 90));
+        assertTrue(NetUtils.matchIpRange("192.168.1.1-65", "192.168.1.63", 90));
+        assertFalse(NetUtils.matchIpRange("192.168.1.1-61", "192.168.1.63", 90));
+        assertFalse(NetUtils.matchIpRange("192.168.1.62", "192.168.1.63", 90));
+    }
+
+    @Test
+    public void testMatchIpRangeMatchWhenIpv6() throws UnknownHostException {
+        assertTrue(NetUtils.matchIpRange("*.*.*.*", "192.168.1.63", 90));
+        assertTrue(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:*", "234e:0:4567::3d:ff", 90));
+        assertTrue(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:ee", "234e:0:4567::3d:ee", 90));
+        assertTrue(NetUtils.matchIpRange("234e:0:4567::3d:ee", "234e:0:4567::3d:ee", 90));
+        assertTrue(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:0-ff", "234e:0:4567::3d:ee", 90));
+        assertTrue(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:0-ee", "234e:0:4567::3d:ee", 90));
+
+        assertFalse(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:ff", "234e:0:4567::3d:ee", 90));
+        assertFalse(NetUtils.matchIpRange("234e:0:4567:0:0:0:3d:0-ea", "234e:0:4567::3d:ee", 90));
+    }
+
+    @Test
+    public void testMatchIpRangeMatchWhenIpv6Exception() throws UnknownHostException {
+        IllegalArgumentException thrown =
+                assertThrows(IllegalArgumentException.class, () ->
+                        NetUtils.matchIpRange("234e:0:4567::3d:*", "234e:0:4567::3d:ff", 90));
+        assertTrue(thrown.getMessage().contains("If you config ip expression that contains '*'"));
+
+        thrown = assertThrows(IllegalArgumentException.class, () ->
+                        NetUtils.matchIpRange("234e:0:4567:3d", "234e:0:4567::3d:ff", 90));
+        assertTrue(thrown.getMessage().contains("The host is ipv6, but the pattern is not ipv6 pattern"));
+
+        thrown =
+                assertThrows(IllegalArgumentException.class, () ->
+                        NetUtils.matchIpRange("192.168.1.1-65-3", "192.168.1.63", 90));
+        assertTrue(thrown.getMessage().contains("There is wrong format of ip Address"));
+    }
+
+    @Test
+    public void testMatchIpRangeMatchWhenIpWrongException() throws UnknownHostException {
+        UnknownHostException thrown =
+                assertThrows(UnknownHostException.class, () ->
+                        NetUtils.matchIpRange("192.168.1.63", "192.168.1.ff", 90));
+        assertTrue(thrown.getMessage().contains("192.168.1.ff"));
+    }
+
+    @Test
+    public void testMatchIpMatch() throws UnknownHostException {
+        assertTrue(NetUtils.matchIpExpression("192.168.1.*", "192.168.1.63", 90));
+        assertTrue(NetUtils.matchIpExpression("192.168.1.192/26", "192.168.1.199", 90));
+    }
+
+    @Test
+    public void testMatchIpv6WithIpPort() throws UnknownHostException {
+        assertTrue(NetUtils.matchIpRange("[234e:0:4567::3d:ee]", "234e:0:4567::3d:ee", 8090));
+        assertTrue(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:ee]", "234e:0:4567::3d:ee", 8090));
+        assertTrue(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:ee]:8090", "234e:0:4567::3d:ee", 8090));
+        assertTrue(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:0-ee]:8090", "234e:0:4567::3d:ee", 8090));
+        assertTrue(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:ee-ff]:8090", "234e:0:4567::3d:ee", 8090));
+        assertTrue(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:*]:90", "234e:0:4567::3d:ff", 90));
+
+        assertFalse(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:ee]:7289", "234e:0:4567::3d:ee", 8090));
+        assertFalse(NetUtils.matchIpRange("[234e:0:4567:0:0:0:3d:ee-ff]:8090", "234e:0:4567::3d:ee", 9090));
+    }
+
+    @Test
+    public void testMatchIpv4WithIpPort() throws UnknownHostException {
+        NumberFormatException thrown =
+                assertThrows(NumberFormatException.class, () ->NetUtils.matchIpExpression("192.168.1.192/26:90", "192.168.1.199", 90));
+        assertTrue(thrown instanceof NumberFormatException);
+
+        assertTrue(NetUtils.matchIpRange("*.*.*.*:90", "192.168.1.63", 90));
+        assertTrue(NetUtils.matchIpRange("192.168.1.*:90", "192.168.1.63", 90));
+        assertTrue(NetUtils.matchIpRange("192.168.1.63:90", "192.168.1.63", 90));
+        assertTrue(NetUtils.matchIpRange("192.168.1.63-65:90", "192.168.1.63", 90));
+        assertTrue(NetUtils.matchIpRange("192.168.1.1-63:90", "192.168.1.63", 90));
+
+        assertFalse(NetUtils.matchIpRange("*.*.*.*:80", "192.168.1.63", 90));
+        assertFalse(NetUtils.matchIpRange("192.168.1.*:80", "192.168.1.63", 90));
+        assertFalse(NetUtils.matchIpRange("192.168.1.63:80", "192.168.1.63", 90));
+        assertFalse(NetUtils.matchIpRange("192.168.1.63-65:80", "192.168.1.63", 90));
+        assertFalse(NetUtils.matchIpRange("192.168.1.1-63:80", "192.168.1.63", 90));
+
+        assertFalse(NetUtils.matchIpRange("192.168.1.1-61:90", "192.168.1.62", 90));
+        assertFalse(NetUtils.matchIpRange("192.168.1.62:90", "192.168.1.63", 90));
+    }
 }