IPAccessHandler

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@1279 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2010-02-22 01:15:17 +00:00
parent 0b522aee32
commit 22adee9473
2 changed files with 232 additions and 0 deletions

View File

@ -0,0 +1,31 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!-- =============================================================== -->
<!-- Mixin the Statistics Handler -->
<!-- =============================================================== -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Get id="oldhandler" name="handler"/>
<Set name="handler">
<New id="IPAccessHandler" class="org.eclipse.jetty.server.handler.IPAccessHandler">
<Set name="handler"><Ref id="oldhandler"/></Set>
<Set name="white">
<Array type="String">
<Item>127.0.0.1</Item>
<Item>127.0.0.2/*.html</Item>
</Array>
</Set>
<Set name="black">
<Array type="String">
<Item>127.0.0.1/blacklisted</Item>
<Item>127.0.0.2/black.html</Item>
</Array>
</Set>
</New>
</Set>
</Configure>

View File

@ -0,0 +1,201 @@
// ========================================================================
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.server.handler;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request;
/**
* IP Access Handler
* <p>
* Control access to the wrapped handler by the real remote IP.
* The real IP of the connection is used (not the IP reported in the forwarded for headers),
* as this cannot be as easily forged.
* <p>
* Control is provided by white/black lists of both internet addresses and URIs.
* Internet addresses may be absolute (eg 10.1.2.3) or a prefix pattern (eg 10.1.3. ).
* URI patterns follow the servlet specification for simple prefix and suffix wild cards.
* <p>
* An empty white list is treated as match all. If there is at least one entry in the
* white list, then a request must match a white list entry. Black list entries are always
* appied, so that even if an entry matches the white list, a black list entry will override.
* </p>
* <p>
* Examples of match specifications are:
* <ul>
* <li>10.1.2.3 - all requests from IP 10.1.2.3
* <li>10.1.2.3/foo/bar - all requests from IP 10.1.2.3 to URI /foo/bar
* <li>10.1.2.3/foo/* - all requests from IP 10.1.2.3 to URIs starting with /foo/
* <li>10.1.2.3/*.html - all requests from IP 10.1.2.3 to URIs ending with .html
* <li>10.1. - all requests from IPs starting with 10.1.
* <li>10.1./foo/bar - all requests from IPs starting with 10.1. to URI /foo/bar
* <li>10.1./foo/* - all requests from IPs starting with 10.1. to URIs starting with /foo/
* </ul>
* <p>
* Typically, the black/white lists will be used in one of three modes:
* <nl>
* <li>Blocking a few specific IPs/URLs by specifying several black list entries.
* <li>Allowing only some specific IPs/URLs by specifying several white lists entries.
* <li>Allowing a general range of IPs/URLs by specifying serveral general white list
* entries, that are then further refined by several specific black list exceptions
* </ul>
*
*/
public class IPAccessHandler extends HandlerWrapper
{
Map<String,PathMap> _whiteAddr = new HashMap<String, PathMap>();
List<String> _whitePattern = new CopyOnWriteArrayList<String>();
Map<String,PathMap> _blackAddr = new HashMap<String, PathMap>();
List<String> _blackPattern = new CopyOnWriteArrayList<String>();
/**
*/
public IPAccessHandler()
{
}
public void addBlack(String addrPath)
{
add(addrPath, _blackAddr, _blackPattern);
}
public void addWhite(String addrPath)
{
add(addrPath, _whiteAddr, _whitePattern);
}
public void setBlack(String[] addrPaths)
{
set(addrPaths, _blackAddr, _blackPattern);
}
public void setWhite(String[] addrPaths)
{
set(addrPaths, _whiteAddr, _whitePattern);
}
/**
*/
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
// Get the real remote IP (not the one set by the forwarded headers (which may be forged))
HttpConnection connection = baseRequest.getConnection();
if (connection!=null)
{
EndPoint endp=connection.getEndPoint();
if (endp!=null)
{
String addr = endp.getRemoteAddr();
if (addr!=null && !isAddrUriAllowed(addr,baseRequest.getPathInfo()))
{
response.sendError(HttpStatus.FORBIDDEN_403);
baseRequest.setHandled(true);
return;
}
}
}
getHandler().handle(target,baseRequest, request, response);
}
protected void add(String addrPath, Map<String,PathMap> addrMap, List<String> patternList)
{
int idx = addrPath.indexOf('/');
String addr = idx > 0 ? addrPath.substring(0,idx) : addrPath;
String path = idx > 0 ? addrPath.substring(idx) : null;
if (path!=null && path.length()>1 && path.charAt(1)=='*')
path=path.substring(1);
System.err.println("addr="+addr+" path="+path);
PathMap map = addrMap.get(addr);
if (map==null)
{
map = new PathMap(true);
addrMap.put(addr,map);
if (addr.endsWith("."))
patternList.add(addr);
}
if (path != null)
map.put(path,path);
}
protected void set(String[] addrPaths, Map<String,PathMap> addrMap, List<String> patternList)
{
addrMap.clear();
patternList.clear();
for (String addrPath:addrPaths)
add(addrPath, addrMap, patternList);
}
protected boolean isAddrUriAllowed(String addr, String path)
{
if (_whiteAddr.size()>0)
{
PathMap white=_whiteAddr.get(addr);
if (white==null || (white.size()>0 && white.match(path)==null))
{
boolean match=false;
for (String pattern:_whitePattern)
{
if (addr.startsWith(pattern))
{
white=_whiteAddr.get(pattern);
if (white!=null && white.size()>0 && white.match(path)!=null)
{
match=true;
break;
}
}
}
if (!match)
return false;
}
}
PathMap black=_blackAddr.get(addr);
if (black!=null && (black.size()==0 || black.match(path)!=null))
return false;
for (String pattern:_blackPattern)
{
if (addr.startsWith(pattern))
{
black=_blackAddr.get(pattern);
if (black!=null && black.match(path)!=null)
return false;
break;
}
}
return true;
}
}