View Javadoc

    1   /*
    2    * Copyright 2012 The Netty Project
    3    *
    4    * The Netty Project licenses this file to you under the Apache License,
    5    * version 2.0 (the "License"); you may not use this file except in compliance
    6    * with the License. You may obtain a copy of the License at:
    7    *
    8    *   http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    13   * License for the specific language governing permissions and limitations
    14   * under the License.
    15   */
    16  package org.jboss.netty.handler.ipfilter;
    17
    18  import java.net.InetAddress;
    19  import java.net.InetSocketAddress;
    20  import java.util.Collection;
    21  import java.util.Iterator;
    22  import java.util.List;
    23  import java.util.concurrent.CopyOnWriteArrayList;
    24
    25  import org.jboss.netty.channel.ChannelEvent;
    26  import org.jboss.netty.channel.ChannelHandler.Sharable;
    27  import org.jboss.netty.channel.ChannelHandlerContext;
    28
    29  /**
    30   * Implementation of Filter of IP based on ALLOW and DENY rules.<br>
    31   * <br><br>
    32   * This implementation could be changed by implementing a new {@link IpFilterRule} than default
    33   * {@link IpV4SubnetFilterRule} (IPV4 support only), {@link IpSubnetFilterRule} (IPV4 and IPV6 support)
    34   * or {@link IpFilterRule} (IP and host name string pattern support) .<br>
    35   * <br>
    36   * The check is done by going from step to step in the underlying array of IpFilterRule.<br>
    37   * Each {@link IpFilterRule} answers to the method accept if the {@link InetAddress} is accepted or not,
    38   * according to its implementation. If an InetAddress arrives at the end of the list, as in Firewall
    39   * usual rules, the InetAddress is therefore accepted by default.<br>
    40   * <ul>
    41   * <li>If it was constructed with True as first argument,
    42   * the IpFilterRule is an ALLOW rule (every InetAddress that fits in the rule will be accepted).</li>
    43   * <li>If it was constructed with False as first argument,
    44   * the IpFilterRule is a DENY rule (every InetAddress that fits in the rule will be refused).</li>
    45   * </ul><br>
    46   * <br>
    47   * An empty list means allow all (no limitation).<br><br>
    48   * <b>For efficiency reason, you should not add/remove too frequently IpFilterRules to/from this handler.
    49   * You should prefer to replace an entry (<tt>set</tt> method) with an ALLOW/DENY ALL IpFilterRule
    50   * if possible.</b><br><br><br>
    51   * <b>This handler should be created only once and reused on every pipeline since it handles
    52   * a global status of what is allowed or blocked.</b><br><br>
    53   * <p/>
    54   * Note that {@link IpSubnetFilterRule} which supports IPV4 and IPV6 should be used with as much as
    55   * possible no mixed IP protocol. Both IPV4 and IPV6 are supported but a mix (IpFilter in IPV6 notation
    56   * and the address from the channel in IPV4, or the reverse) can lead to wrong result.
    57   */
    58  @Sharable
    59  public class IpFilterRuleHandler extends IpFilteringHandlerImpl {
    60      /** List of {@link IpFilterRule} */
    61      private final CopyOnWriteArrayList<IpFilterRule> ipFilterRuleList = new CopyOnWriteArrayList<IpFilterRule>();
    62
    63      /** Constructor from a new list of IpFilterRule */
    64      public IpFilterRuleHandler(List<IpFilterRule> newList) {
    65          if (newList != null) {
    66              ipFilterRuleList.addAll(newList);
    67          }
    68      }
    69
    70      /**
    71       * Empty constructor (no IpFilterRule in the List at construction). In such a situation,
    72       * empty list implies allow all.
    73       */
    74      public IpFilterRuleHandler() {
    75      }
    76
    77      // Below are methods directly inspired from CopyOnWriteArrayList methods
    78
    79      /** Add an ipFilterRule in the list at the end */
    80      public void add(IpFilterRule ipFilterRule) {
    81          if (ipFilterRule == null) {
    82              throw new NullPointerException("IpFilterRule can not be null");
    83          }
    84          ipFilterRuleList.add(ipFilterRule);
    85      }
    86
    87      /** Add an ipFilterRule in the list at the specified position (shifting to the right other elements) */
    88      public void add(int index, IpFilterRule ipFilterRule) {
    89          if (ipFilterRule == null) {
    90              throw new NullPointerException("IpFilterRule can not be null");
    91          }
    92          ipFilterRuleList.add(index, ipFilterRule);
    93      }
    94
    95      /**
    96       * Appends all of the elements in the specified collection to the end of this list,
    97       * in the order that they are returned by the specified collection's iterator.
    98       */
    99      public void addAll(Collection<IpFilterRule> c) {
    100         if (c == null) {
    101             throw new NullPointerException("Collection can not be null");
    102         }
    103         ipFilterRuleList.addAll(c);
    104     }
    105
    106     /** Inserts all of the elements in the specified collection into this list, starting at the specified position. */
    107     public void addAll(int index, Collection<IpFilterRule> c) {
    108         if (c == null) {
    109             throw new NullPointerException("Collection can not be null");
    110         }
    111         ipFilterRuleList.addAll(index, c);
    112     }
    113
    114     /**
    115      * Append the element if not present.
    116      *
    117      * @return the number of elements added
    118      */
    119     public int addAllAbsent(Collection<IpFilterRule> c) {
    120         if (c == null) {
    121             throw new NullPointerException("Collection can not be null");
    122         }
    123         return ipFilterRuleList.addAllAbsent(c);
    124     }
    125
    126     /**
    127      * Append the element if not present.
    128      *
    129      * @return true if the element was added
    130      */
    131     public boolean addIfAbsent(IpFilterRule ipFilterRule) {
    132         if (ipFilterRule == null) {
    133             throw new NullPointerException("IpFilterRule can not be null");
    134         }
    135         return ipFilterRuleList.addIfAbsent(ipFilterRule);
    136     }
    137
    138     /** Clear the list */
    139     public void clear() {
    140         ipFilterRuleList.clear();
    141     }
    142
    143     /**
    144      * Returns true if this list contains the specified element
    145      *
    146      * @return true if this list contains the specified element
    147      */
    148     public boolean contains(IpFilterRule ipFilterRule) {
    149         if (ipFilterRule == null) {
    150             throw new NullPointerException("IpFilterRule can not be null");
    151         }
    152         return ipFilterRuleList.contains(ipFilterRule);
    153     }
    154
    155     /**
    156      * Returns true if this list contains all of the elements of the specified collection
    157      *
    158      * @return true if this list contains all of the elements of the specified collection
    159      */
    160     public boolean containsAll(Collection<IpFilterRule> c) {
    161         if (c == null) {
    162             throw new NullPointerException("Collection can not be null");
    163         }
    164         return ipFilterRuleList.containsAll(c);
    165     }
    166
    167     /**
    168      * Returns the element at the specified position in this list
    169      *
    170      * @return the element at the specified position in this list
    171      */
    172     public IpFilterRule get(int index) {
    173         return ipFilterRuleList.get(index);
    174     }
    175
    176     /**
    177      * Returns true if this list contains no elements
    178      *
    179      * @return true if this list contains no elements
    180      */
    181     public boolean isEmpty() {
    182         return ipFilterRuleList.isEmpty();
    183     }
    184
    185     /** Remove the ipFilterRule from the list */
    186     public void remove(IpFilterRule ipFilterRule) {
    187         if (ipFilterRule == null) {
    188             throw new NullPointerException("IpFilterRule can not be null");
    189         }
    190         ipFilterRuleList.remove(ipFilterRule);
    191     }
    192
    193     /**
    194      * Removes the element at the specified position in this list
    195      *
    196      * @return the element previously at the specified position
    197      */
    198     public IpFilterRule remove(int index) {
    199         return ipFilterRuleList.remove(index);
    200     }
    201
    202     /** Removes from this list all of its elements that are contained in the specified collection */
    203     public void removeAll(Collection<IpFilterRule> c) {
    204         if (c == null) {
    205             throw new NullPointerException("Collection can not be null");
    206         }
    207         ipFilterRuleList.removeAll(c);
    208     }
    209
    210     /** Retains only the elements in this list that are contained in the specified collection */
    211     public void retainAll(Collection<IpFilterRule> c) {
    212         if (c == null) {
    213             throw new NullPointerException("Collection can not be null");
    214         }
    215         ipFilterRuleList.retainAll(c);
    216     }
    217
    218     /**
    219      * Replaces the element at the specified position in this list with the specified element
    220      *
    221      * @return the element previously at the specified position
    222      */
    223     public IpFilterRule set(int index, IpFilterRule ipFilterRule) {
    224         if (ipFilterRule == null) {
    225             throw new NullPointerException("IpFilterRule can not be null");
    226         }
    227         return ipFilterRuleList.set(index, ipFilterRule);
    228     }
    229
    230     /**
    231      * Returns the number of elements in this list.
    232      *
    233      * @return the number of elements in this list.
    234      */
    235     public int size() {
    236         return ipFilterRuleList.size();
    237     }
    238
    239     @Override
    240     protected boolean accept(ChannelHandlerContext ctx, ChannelEvent e, InetSocketAddress inetSocketAddress)
    241             throws Exception {
    242         if (ipFilterRuleList.isEmpty()) {
    243             // No limitation neither in deny or allow, so accept
    244             return true;
    245         }
    246         InetAddress inetAddress = inetSocketAddress.getAddress();
    247         Iterator<IpFilterRule> iterator = ipFilterRuleList.iterator();
    248         IpFilterRule ipFilterRule = null;
    249         while (iterator.hasNext()) {
    250             ipFilterRule = iterator.next();
    251             if (ipFilterRule.contains(inetAddress)) {
    252                 // Match founds, is it a ALLOW or DENY rule
    253                 return ipFilterRule.isAllowRule();
    254             }
    255         }
    256         // No limitation founds and no allow either, but as it is like Firewall rules, it is therefore accepted
    257         return true;
    258     }
    259
    260 }