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      private final List<Subnet> blacklist = new CopyOnWriteArrayList<Subnet>();
45  
46      private final static Logger LOGGER = LoggerFactory.getLogger(BlacklistFilter.class);
47  
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 IllegalArgumentException("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 IllegalArgumentException("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 IllegalArgumentException("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 IllegalArgumentException("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 IllegalArgumentException("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 IllegalArgumentException("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 IllegalArgumentException("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 IllegalArgumentException("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) 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) throws Exception {
187         if (!isBlocked(session)) {
188             // forward if not blocked
189             nextFilter.sessionClosed(session);
190         } else {
191             blockSession(session);
192         }
193     }
194 
195     @Override
196     public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception {
197         if (!isBlocked(session)) {
198             // forward if not blocked
199             nextFilter.sessionIdle(session, status);
200         } else {
201             blockSession(session);
202         }
203     }
204 
205     @Override
206     public void messageReceived(NextFilter nextFilter, IoSession session, Object message) {
207         if (!isBlocked(session)) {
208             // forward if not blocked
209             nextFilter.messageReceived(session, message);
210         } else {
211             blockSession(session);
212         }
213     }
214 
215     @Override
216     public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
217         if (!isBlocked(session)) {
218             // forward if not blocked
219             nextFilter.messageSent(session, writeRequest);
220         } else {
221             blockSession(session);
222         }
223     }
224 
225     private void blockSession(IoSession session) {
226         LOGGER.warn("Remote address in the blacklist; closing.");
227         session.close(true);
228     }
229 
230     private boolean isBlocked(IoSession session) {
231         SocketAddress remoteAddress = session.getRemoteAddress();
232         if (remoteAddress instanceof InetSocketAddress) {
233             InetAddress address = ((InetSocketAddress) remoteAddress).getAddress();
234 
235             // check all subnets
236             for (Subnet subnet : blacklist) {
237                 if (subnet.inSubnet(address)) {
238                     return true;
239                 }
240             }
241         }
242 
243         return false;
244     }
245 }