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     public void block(InetAddress address) {
133         if (address == null) {
134             throw new IllegalArgumentException("Adress to block can not be null");
135         }
136 
137         block(new Subnet(address, 32));
138     }
139 
140     /**
141      * Blocks the specified subnet.
142      */
143     public void block(Subnet subnet) {
144         if (subnet == null) {
145             throw new IllegalArgumentException("Subnet can not be null");
146         }
147 
148         blacklist.add(subnet);
149     }
150 
151     /**
152      * Unblocks the specified endpoint.
153      */
154     public void unblock(InetAddress address) {
155         if (address == null) {
156             throw new IllegalArgumentException("Adress to unblock can not be null");
157         }
158 
159         unblock(new Subnet(address, 32));
160     }
161 
162     /**
163      * Unblocks the specified subnet.
164      */
165     public void unblock(Subnet subnet) {
166         if (subnet == null) {
167             throw new IllegalArgumentException("Subnet can not be null");
168         }
169 
170         blacklist.remove(subnet);
171     }
172 
173     @Override
174     public void sessionCreated(NextFilter nextFilter, IoSession session) {
175         if (!isBlocked(session)) {
176             // forward if not blocked
177             nextFilter.sessionCreated(session);
178         } else {
179             blockSession(session);
180         }
181     }
182 
183     @Override
184     public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
185         if (!isBlocked(session)) {
186             // forward if not blocked
187             nextFilter.sessionOpened(session);
188         } else {
189             blockSession(session);
190         }
191     }
192 
193     @Override
194     public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {
195         if (!isBlocked(session)) {
196             // forward if not blocked
197             nextFilter.sessionClosed(session);
198         } else {
199             blockSession(session);
200         }
201     }
202 
203     @Override
204     public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception {
205         if (!isBlocked(session)) {
206             // forward if not blocked
207             nextFilter.sessionIdle(session, status);
208         } else {
209             blockSession(session);
210         }
211     }
212 
213     @Override
214     public void messageReceived(NextFilter nextFilter, IoSession session, Object message) {
215         if (!isBlocked(session)) {
216             // forward if not blocked
217             nextFilter.messageReceived(session, message);
218         } else {
219             blockSession(session);
220         }
221     }
222 
223     @Override
224     public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
225         if (!isBlocked(session)) {
226             // forward if not blocked
227             nextFilter.messageSent(session, writeRequest);
228         } else {
229             blockSession(session);
230         }
231     }
232 
233     private void blockSession(IoSession session) {
234         LOGGER.warn("Remote address in the blacklist; closing.");
235         session.close(true);
236     }
237 
238     private boolean isBlocked(IoSession session) {
239         SocketAddress remoteAddress = session.getRemoteAddress();
240 
241         if (remoteAddress instanceof InetSocketAddress) {
242             InetAddress address = ((InetSocketAddress) remoteAddress).getAddress();
243 
244             // check all subnets
245             for (Subnet subnet : blacklist) {
246                 if (subnet.inSubnet(address)) {
247                     return true;
248                 }
249             }
250         }
251 
252         return false;
253     }
254 }