View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.filter.firewall;
21  
22  import java.net.InetAddress;
23  import java.net.InetSocketAddress;
24  import java.net.SocketAddress;
25  import java.util.List;
26  import java.util.concurrent.CopyOnWriteArrayList;
27  
28  import org.apache.mina.core.filterchain.IoFilter;
29  import org.apache.mina.core.filterchain.IoFilterAdapter;
30  import org.apache.mina.core.session.IdleStatus;
31  import org.apache.mina.core.session.IoSession;
32  import org.apache.mina.core.write.WriteRequest;
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  
36  /**
37   * A {@link IoFilter} which blocks connections from blacklisted remote
38   * address.
39   *
40   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
41   * @org.apache.xbean.XBean
42   */
43  public class BlacklistFilter extends IoFilterAdapter {
44      /** The list of blocked addresses */
45      private final List<Subnet> blacklist = new CopyOnWriteArrayList<Subnet>();
46  
47      private final static Logger LOGGER = LoggerFactory.getLogger(BlacklistFilter.class);
48  
49      /**
50       * Sets the addresses to be blacklisted.
51       *
52       * NOTE: this call will remove any previously blacklisted addresses.
53       *
54       * @param addresses an array of addresses to be blacklisted.
55       */
56      public void setBlacklist(InetAddress[] addresses) {
57          if (addresses == null) {
58              throw new IllegalArgumentException("addresses");
59          }
60  
61          blacklist.clear();
62  
63          for (int i = 0; i < addresses.length; i++) {
64              InetAddress addr = addresses[i];
65              block(addr);
66          }
67      }
68  
69      /**
70       * Sets the subnets to be blacklisted.
71       *
72       * NOTE: this call will remove any previously blacklisted subnets.
73       *
74       * @param subnets an array of subnets to be blacklisted.
75       */
76      public void setSubnetBlacklist(Subnet[] subnets) {
77          if (subnets == null) {
78              throw new IllegalArgumentException("Subnets must not be null");
79          }
80  
81          blacklist.clear();
82  
83          for (Subnet subnet : subnets) {
84              block(subnet);
85          }
86      }
87  
88      /**
89       * Sets the addresses to be blacklisted.
90       *
91       * NOTE: this call will remove any previously blacklisted addresses.
92       *
93       * @param addresses a collection of InetAddress objects representing the
94       *        addresses to be blacklisted.
95       * @throws IllegalArgumentException if the specified collections contains
96       *         non-{@link InetAddress} objects.
97       */
98      public void setBlacklist(Iterable<InetAddress> addresses) {
99          if (addresses == null) {
100             throw new IllegalArgumentException("addresses");
101         }
102 
103         blacklist.clear();
104 
105         for (InetAddress address : addresses) {
106             block(address);
107         }
108     }
109 
110     /**
111      * Sets the subnets to be blacklisted.
112      *
113      * NOTE: this call will remove any previously blacklisted subnets.
114      *
115      * @param subnets an array of subnets to be blacklisted.
116      */
117     public void setSubnetBlacklist(Iterable<Subnet> subnets) {
118         if (subnets == null) {
119             throw new IllegalArgumentException("Subnets must not be null");
120         }
121 
122         blacklist.clear();
123 
124         for (Subnet subnet : subnets) {
125             block(subnet);
126         }
127     }
128 
129     /**
130      * Blocks the specified endpoint.
131      * 
132      * @param address The address to block
133      */
134     public void block(InetAddress address) {
135         if (address == null) {
136             throw new IllegalArgumentException("Adress to block can not be null");
137         }
138 
139         block(new Subnet(address, 32));
140     }
141 
142     /**
143      * Blocks the specified subnet.
144      * 
145      * @param subnet The subnet to block
146      */
147     public void block(Subnet subnet) {
148         if (subnet == null) {
149             throw new IllegalArgumentException("Subnet can not be null");
150         }
151 
152         blacklist.add(subnet);
153     }
154 
155     /**
156      * Unblocks the specified endpoint.
157      * 
158      * @param address The address to unblock
159      */
160     public void unblock(InetAddress address) {
161         if (address == null) {
162             throw new IllegalArgumentException("Adress to unblock can not be null");
163         }
164 
165         unblock(new Subnet(address, 32));
166     }
167 
168     /**
169      * Unblocks the specified subnet.
170      * 
171      * @param subnet The subnet to unblock
172      */
173     public void unblock(Subnet subnet) {
174         if (subnet == null) {
175             throw new IllegalArgumentException("Subnet can not be null");
176         }
177 
178         blacklist.remove(subnet);
179     }
180 
181     @Override
182     public void sessionCreated(NextFilter nextFilter, IoSession session) {
183         if (!isBlocked(session)) {
184             // forward if not blocked
185             nextFilter.sessionCreated(session);
186         } else {
187             blockSession(session);
188         }
189     }
190 
191     @Override
192     public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
193         if (!isBlocked(session)) {
194             // forward if not blocked
195             nextFilter.sessionOpened(session);
196         } else {
197             blockSession(session);
198         }
199     }
200 
201     @Override
202     public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {
203         if (!isBlocked(session)) {
204             // forward if not blocked
205             nextFilter.sessionClosed(session);
206         } else {
207             blockSession(session);
208         }
209     }
210 
211     @Override
212     public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception {
213         if (!isBlocked(session)) {
214             // forward if not blocked
215             nextFilter.sessionIdle(session, status);
216         } else {
217             blockSession(session);
218         }
219     }
220 
221     @Override
222     public void messageReceived(NextFilter nextFilter, IoSession session, Object message) {
223         if (!isBlocked(session)) {
224             // forward if not blocked
225             nextFilter.messageReceived(session, message);
226         } else {
227             blockSession(session);
228         }
229     }
230 
231     @Override
232     public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
233         if (!isBlocked(session)) {
234             // forward if not blocked
235             nextFilter.messageSent(session, writeRequest);
236         } else {
237             blockSession(session);
238         }
239     }
240 
241     private void blockSession(IoSession session) {
242         LOGGER.warn("Remote address in the blacklist; closing.");
243         session.closeNow();
244     }
245 
246     private boolean isBlocked(IoSession session) {
247         SocketAddress remoteAddress = session.getRemoteAddress();
248 
249         if (remoteAddress instanceof InetSocketAddress) {
250             InetAddress address = ((InetSocketAddress) remoteAddress).getAddress();
251 
252             // check all subnets
253             for (Subnet subnet : blacklist) {
254                 if (subnet.inSubnet(address)) {
255                     return true;
256                 }
257             }
258         }
259 
260         return false;
261     }
262 }