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.apache.mina.filter.FilterEvent;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  
37  /**
38   * A {@link IoFilter} which blocks connections from blacklisted remote
39   * address.
40   *
41   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
42   * @org.apache.xbean.XBean
43   */
44  public class BlacklistFilter extends IoFilterAdapter {
45      /** The list of blocked addresses */
46      private final List<Subnet> blacklist = new CopyOnWriteArrayList<Subnet>();
47  
48      /** A logger for this class */ 
49      private final static Logger LOGGER = LoggerFactory.getLogger(BlacklistFilter.class);
50  
51      /**
52       * Sets the addresses to be blacklisted.
53       *
54       * NOTE: this call will remove any previously blacklisted addresses.
55       *
56       * @param addresses an array of addresses to be blacklisted.
57       */
58      public void setBlacklist(InetAddress[] addresses) {
59          if (addresses == null) {
60              throw new IllegalArgumentException("addresses");
61          }
62  
63          blacklist.clear();
64  
65          for (InetAddress address:addresses) {
66              block(address);
67          }
68      }
69  
70      /**
71       * Sets the subnets to be blacklisted.
72       *
73       * NOTE: this call will remove any previously blacklisted subnets.
74       *
75       * @param subnets an array of subnets to be blacklisted.
76       */
77      public void setSubnetBlacklist(Subnet[] subnets) {
78          if (subnets == null) {
79              throw new IllegalArgumentException("Subnets must not be null");
80          }
81  
82          blacklist.clear();
83  
84          for (Subnet subnet : subnets) {
85              block(subnet);
86          }
87      }
88  
89      /**
90       * Sets the addresses to be blacklisted.
91       *
92       * NOTE: this call will remove any previously blacklisted addresses.
93       *
94       * @param addresses a collection of InetAddress objects representing the
95       *        addresses to be blacklisted.
96       * @throws IllegalArgumentException if the specified collections contains
97       *         non-{@link InetAddress} objects.
98       */
99      public void setBlacklist(Iterable<InetAddress> addresses) {
100         if (addresses == null) {
101             throw new IllegalArgumentException("addresses");
102         }
103 
104         blacklist.clear();
105 
106         for (InetAddress address : addresses) {
107             block(address);
108         }
109     }
110 
111     /**
112      * Sets the subnets to be blacklisted.
113      *
114      * NOTE: this call will remove any previously blacklisted subnets.
115      *
116      * @param subnets an array of subnets to be blacklisted.
117      */
118     public void setSubnetBlacklist(Iterable<Subnet> subnets) {
119         if (subnets == null) {
120             throw new IllegalArgumentException("Subnets must not be null");
121         }
122 
123         blacklist.clear();
124 
125         for (Subnet subnet : subnets) {
126             block(subnet);
127         }
128     }
129 
130     /**
131      * Blocks the specified endpoint.
132      * 
133      * @param address The address to block
134      */
135     public void block(InetAddress address) {
136         if (address == null) {
137             throw new IllegalArgumentException("Adress to block can not be null");
138         }
139 
140         block(new Subnet(address, 32));
141     }
142 
143     /**
144      * Blocks the specified subnet.
145      * 
146      * @param subnet The subnet to block
147      */
148     public void block(Subnet subnet) {
149         if (subnet == null) {
150             throw new IllegalArgumentException("Subnet can not be null");
151         }
152 
153         blacklist.add(subnet);
154     }
155 
156     /**
157      * Unblocks the specified endpoint.
158      * 
159      * @param address The address to unblock
160      */
161     public void unblock(InetAddress address) {
162         if (address == null) {
163             throw new IllegalArgumentException("Adress to unblock can not be null");
164         }
165 
166         unblock(new Subnet(address, 32));
167     }
168 
169     /**
170      * Unblocks the specified subnet.
171      * 
172      * @param subnet The subnet to unblock
173      */
174     public void unblock(Subnet subnet) {
175         if (subnet == null) {
176             throw new IllegalArgumentException("Subnet can not be null");
177         }
178 
179         blacklist.remove(subnet);
180     }
181 
182     /**
183      * {@inheritDoc}
184      */
185     @Override
186     public void event(NextFilter nextFilter, IoSession session, FilterEvent event) throws Exception {
187         if (!isBlocked(session)) {
188             // forward if not blocked
189             nextFilter.event(session, event);
190         } else {
191             blockSession(session);
192         }
193     }
194 
195     /**
196      * {@inheritDoc}
197      */
198     @Override
199     public void sessionCreated(NextFilter nextFilter, IoSession session) {
200         if (!isBlocked(session)) {
201             // forward if not blocked
202             nextFilter.sessionCreated(session);
203         } else {
204             blockSession(session);
205         }
206     }
207 
208     /**
209      * {@inheritDoc}
210      */
211     @Override
212     public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
213         if (!isBlocked(session)) {
214             // forward if not blocked
215             nextFilter.sessionOpened(session);
216         } else {
217             blockSession(session);
218         }
219     }
220 
221     /**
222      * {@inheritDoc}
223      */
224     @Override
225     public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception {
226         if (!isBlocked(session)) {
227             // forward if not blocked
228             nextFilter.sessionIdle(session, status);
229         } else {
230             blockSession(session);
231         }
232     }
233 
234     /**
235      * {@inheritDoc}
236      */
237     @Override
238     public void messageReceived(NextFilter nextFilter, IoSession session, Object message) {
239         if (!isBlocked(session)) {
240             // forward if not blocked
241             nextFilter.messageReceived(session, message);
242         } else {
243             blockSession(session);
244         }
245     }
246 
247     /**
248      * {@inheritDoc}
249      */
250     @Override
251     public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
252         if (!isBlocked(session)) {
253             // forward if not blocked
254             nextFilter.messageSent(session, writeRequest);
255         } else {
256             blockSession(session);
257         }
258     }
259 
260     private void blockSession(IoSession session) {
261         LOGGER.warn("Remote address in the blacklist; closing.");
262         session.closeNow();
263     }
264 
265     private boolean isBlocked(IoSession session) {
266         SocketAddress remoteAddress = session.getRemoteAddress();
267 
268         if (remoteAddress instanceof InetSocketAddress) {
269             InetAddress address = ((InetSocketAddress) remoteAddress).getAddress();
270 
271             // check all subnets
272             for (Subnet subnet : blacklist) {
273                 if (subnet.inSubnet(address)) {
274                     return true;
275                 }
276             }
277         }
278 
279         return false;
280     }
281 }