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