2011-04-13 15:28:28 +02:00
//
// AbstractRemoteHandler
// Copyright 2011 by Florian Richter
// First released 2011 at http://yacy.net
//
// $LastChangedDate$
// $LastChangedRevision$
// $LastChangedBy$
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program in the file lgpl21.txt
// If not, see <http://www.gnu.org/licenses/>.
//
package net.yacy.http ;
import java.io.IOException ;
2013-10-01 03:04:32 +02:00
import java.net.InetAddress ;
2011-04-13 15:28:28 +02:00
import java.util.LinkedList ;
import java.util.List ;
2014-01-06 15:00:14 +01:00
import java.util.StringTokenizer ;
2011-04-13 15:28:28 +02:00
import javax.servlet.ServletException ;
import javax.servlet.http.HttpServletRequest ;
import javax.servlet.http.HttpServletResponse ;
2014-05-21 03:04:07 +02:00
import net.yacy.cora.protocol.Domains ;
import net.yacy.cora.protocol.HeaderFramework ;
2014-01-07 01:01:55 +01:00
import net.yacy.repository.Blacklist.BlacklistType ;
2012-06-29 21:16:20 +02:00
import net.yacy.search.Switchboard ;
2014-05-21 03:04:07 +02:00
import org.eclipse.jetty.proxy.ConnectHandler ;
2011-04-13 15:28:28 +02:00
import org.eclipse.jetty.server.Handler ;
import org.eclipse.jetty.server.Request ;
/ * *
* abstract jetty http handler
* only request to remote hosts ( proxy requests ) are processed by derived classes
* /
2014-05-21 03:04:07 +02:00
abstract public class AbstractRemoteHandler extends ConnectHandler implements Handler {
2011-04-13 15:28:28 +02:00
2014-07-10 02:09:26 +02:00
protected Switchboard sb = null ;
2014-09-07 12:28:19 +02:00
private final List < String > localVirtualHostNames = new LinkedList < String > ( ) ; // list for quick check for req to local peer
2013-10-01 03:04:32 +02:00
@Override
2014-05-21 03:04:07 +02:00
protected void doStart ( ) throws Exception {
super . doStart ( ) ;
2014-09-07 12:28:19 +02:00
this . sb = Switchboard . getSwitchboard ( ) ;
this . localVirtualHostNames . add ( " localhost " ) ;
this . localVirtualHostNames . add ( sb . getConfig ( " fileHost " , " localpeer " ) ) ;
2011-04-13 15:28:28 +02:00
2014-09-07 12:28:19 +02:00
// Add some other known local host names
// The remote DNS sometimes takes very long when it is waiting for timeout, therefore we do this concurrently
new Thread ( ) {
@Override
public void run ( ) {
final InetAddress localInetAddress = Domains . myPublicLocalIP ( ) ;
if ( localInetAddress ! = null ) {
if ( ! localVirtualHostNames . contains ( localInetAddress . getHostName ( ) ) ) {
localVirtualHostNames . add ( localInetAddress . getHostName ( ) ) ;
localVirtualHostNames . add ( localInetAddress . getHostAddress ( ) ) ; // same as getServer().getURI().getHost()
}
2013-10-01 03:04:32 +02:00
2014-09-07 12:28:19 +02:00
if ( ! localVirtualHostNames . contains ( localInetAddress . getCanonicalHostName ( ) ) ) {
localVirtualHostNames . add ( localInetAddress . getCanonicalHostName ( ) ) ;
}
}
if ( sb . peers ! = null ) {
localVirtualHostNames . add ( sb . peers . mySeed ( ) . getIP ( ) ) ;
localVirtualHostNames . add ( sb . peers . myAlternativeAddress ( ) ) ; // add the "peername.yacy" address
localVirtualHostNames . add ( sb . peers . mySeed ( ) . getHexHash ( ) + " .yacyh " ) ; // bugfix by P. Dahl
}
2013-10-01 03:04:32 +02:00
}
2014-09-07 12:28:19 +02:00
} . start ( ) ;
2013-10-01 03:04:32 +02:00
}
2011-04-13 15:28:28 +02:00
2013-10-01 03:04:32 +02:00
abstract public void handleRemote ( String target , Request baseRequest , HttpServletRequest request ,
HttpServletResponse response ) throws IOException , ServletException ;
@Override
public void handle ( String target , Request baseRequest , HttpServletRequest request ,
HttpServletResponse response ) throws IOException , ServletException {
2014-03-02 12:10:19 +01:00
2013-10-01 03:04:32 +02:00
String host = request . getHeader ( " Host " ) ;
if ( host = = null ) return ; // no proxy request, continue processing by handlers
2014-10-01 10:21:03 +02:00
String hostOnly = Domains . stripToHostName ( host ) ;
2014-03-02 12:10:19 +01:00
2013-10-01 03:04:32 +02:00
if ( localVirtualHostNames . contains ( hostOnly ) ) return ; // no proxy request (quick check), continue processing by handlers
if ( Domains . isLocal ( hostOnly , null ) ) return ; // no proxy, continue processing by handlers
2014-10-01 15:32:10 +02:00
if ( sb . peers . myIPs ( ) . contains ( hostOnly ) ) { // remote access to my external IP, continue processing by handlers
localVirtualHostNames . addAll ( sb . peers . myIPs ( ) ) ; // not available on init, add it now for quickcheck
2013-10-01 03:04:32 +02:00
return ;
}
2014-01-03 01:13:56 +01:00
InetAddress resolvedIP = Domains . dnsResolve ( hostOnly ) ; // during testing isLocal() failed to resolve domain against publicIP
2014-10-01 15:32:10 +02:00
if ( resolvedIP ! = null & & sb . myPublicIPs ( ) . contains ( resolvedIP . getHostAddress ( ) ) ) {
2014-01-03 01:13:56 +01:00
localVirtualHostNames . add ( resolvedIP . getHostName ( ) ) ; // remember resolved hostname
2014-01-03 12:28:40 +01:00
//localVirtualHostNames.add(resolved.getHostAddress()); // might change ?
2014-01-03 01:13:56 +01:00
return ;
}
2014-01-02 09:11:08 +01:00
// from here we can assume it is a proxy request
// should check proxy use permission
if ( ! Switchboard . getSwitchboard ( ) . getConfigBool ( " isTransparentProxy " , false ) ) {
// transparent proxy not swiched on
2014-02-28 03:14:07 +01:00
response . sendError ( HttpServletResponse . SC_FORBIDDEN , " proxy use not allowed (see Advanced Settings -> HTTP Networking -> Transparent Proxy; switched off). " ) ;
2014-01-02 09:11:08 +01:00
baseRequest . setHandled ( true ) ;
return ;
}
2014-01-01 20:48:35 +01:00
2014-01-06 15:00:14 +01:00
final String remoteHost = request . getRemoteHost ( ) ;
if ( ! proxyippatternmatch ( remoteHost ) ) {
// TODO: handle proxy account
2014-01-02 09:11:08 +01:00
response . sendError ( HttpServletResponse . SC_FORBIDDEN ,
2014-02-28 03:14:07 +01:00
" proxy use not granted for IP " + remoteHost + " (see Advanced Settings -> Proxy Access Settings -> IP-Number filter). " ) ;
2014-01-02 09:11:08 +01:00
baseRequest . setHandled ( true ) ;
return ;
}
2014-01-01 20:48:35 +01:00
2014-01-07 01:01:55 +01:00
// check the blacklist
if ( Switchboard . urlBlacklist . isListed ( BlacklistType . PROXY , hostOnly . toLowerCase ( ) , request . getPathInfo ( ) ) ) {
response . sendError ( HttpServletResponse . SC_FORBIDDEN ,
" URL ' " + hostOnly + " ' blocked by yacy proxy (blacklisted) " ) ;
baseRequest . setHandled ( true ) ;
return ;
}
2014-05-21 03:04:07 +02:00
if ( request . getMethod ( ) . equalsIgnoreCase ( HeaderFramework . METHOD_CONNECT ) ) {
// will be done by the ConnectHandler
super . handle ( target , baseRequest , request , response ) ;
return ;
}
2014-01-07 01:01:55 +01:00
2013-10-01 03:04:32 +02:00
handleRemote ( target , baseRequest , request , response ) ;
2014-01-01 20:48:35 +01:00
2013-10-01 03:04:32 +02:00
}
2014-01-02 09:11:08 +01:00
2014-01-06 15:00:14 +01:00
/ * *
* helper for proxy IP config pattern check
* /
private boolean proxyippatternmatch ( final String key ) {
// the cfgippattern is a comma-separated list of patterns
// each pattern may contain one wildcard-character '*' which matches anything
final String cfgippattern = Switchboard . getSwitchboard ( ) . getConfig ( " proxyClient " , " * " ) ;
if ( cfgippattern . equals ( " * " ) ) {
return true ;
}
final StringTokenizer st = new StringTokenizer ( cfgippattern , " , " ) ;
String pattern ;
while ( st . hasMoreTokens ( ) ) {
pattern = st . nextToken ( ) ;
if ( key . matches ( pattern ) ) {
return true ;
}
}
return false ;
}
2011-04-13 15:28:28 +02:00
}