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