简体   繁体   English

具有Apache Camel的简单HTTPS代理服务器

[英]A simple HTTPS proxy server with Apache Camel

I am trying to implement a simple HTTP proxy service with Apache Camel. 我正在尝试使用Apache Camel实现简单的HTTP代理服务。 My code looks like this: 我的代码如下所示:

from("jetty:http://localhost:80?matchOnUriPrefix=true")
.recipientList(simple("jetty:${in.header.CamelHttpUrl}?bridgeEndpoint=true&throwExceptionOnFailure=false&disableStreamCache=true"));

It is essentially this with a dynamic recipient list to support multiple destinations. 实质上, 这是带有动态收件人列表以支持多个目的地的。 I also had to add the disableStreamCache=true bit, otherwise I would get weird exceptions with path duplication (like /index.html would become /index.html/index.html ). 我还必须添加disableStreamCache=true位,否则我将获得路径重复的奇怪异常(例如/index.html将变成/index.html/index.html )。

Nevertheless, it seems to work. 但是,它似乎有效。 But only with HTTP requests. 但仅适用于HTTP请求。 When I try accessing an HTTPS site, I always get a 404. 当我尝试访问HTTPS站点时,总是得到404。

According to the logs, the jetty component just doesn't seem to find the remote server. 根据日志,码头组件似乎没有找到远程服务器。 I have no idea why. 我不知道为什么。

01:36:37.495 [qtp85415531-22 - www.google.cz:443] DEBUG org.eclipse.jetty.server.Server - REQUEST www.google.cz:443 on AsyncHttpConnection@6964b063,g=HttpGenerator{s=0,h=-1,b=-1,c=-1},p=HttpParser{s=-5,l=17,c=0},r=1
01:36:37.495 [qtp85415531-22 - www.google.cz:443] DEBUG o.e.j.server.handler.ContextHandler - scope null||www.google.cz:443 @ o.e.j.s.ServletContextHandler{/,null}
01:36:37.495 [qtp85415531-22 - www.google.cz:443] DEBUG o.e.j.server.handler.ContextHandler - context=null||www.google.cz:443 @ o.e.j.s.ServletContextHandler{/,null}
01:36:37.495 [qtp85415531-22 - www.google.cz:443] DEBUG o.e.jetty.servlet.ServletHandler - servlet null||www.google.cz:443 -> null
01:36:37.495 [qtp85415531-22 - www.google.cz:443] DEBUG o.e.jetty.servlet.ServletHandler - chain=null
01:36:37.495 [qtp85415531-22 - www.google.cz:443] DEBUG o.e.jetty.servlet.ServletHandler - Not Found www.google.cz:443
01:36:37.495 [qtp85415531-22 - www.google.cz:443] DEBUG org.eclipse.jetty.server.Server - RESPONSE www.google.cz:443  200 handled=false

What should I do to enable this HTTPS support? 我应该怎么做才能启用此HTTPS支持? Is it even possible with standard Camel components? 使用标准骆驼组件甚至可能吗?

Edit: 编辑:

I managed to update my route definition to not use a recipient list. 我设法将路线定义更新为不使用收件人列表。 I don't know whether this improves anything performance-wise (does it?) but it feels better. 我不知道这是否可以改善性能(是吗?),但是感觉更好。 I was also able to remove the path duplication problem when not using disableStreamCache=true by this. 当不使用disableStreamCache=true时,我也能够消除路径重复问题。

from("jetty:http://localhost:80?matchOnUriPrefix=true")
.to("http4:dummy?bridgeEndpoint=true&urlRewrite=#urlRewrite&throwExceptionOnFailure=false");

And the URL rewriter implementation: 和URL重写器的实现:

UrlRewrite urlRewrite = new HttpServletUrlRewrite() {
    @Override
    public String rewrite(String url, String relativeUrl, Producer producer, HttpServletRequest request) throws Exception {
        return request.getRequestURL().toString();
    }

    @Override
    public String rewrite(String url, String relativeUrl, Producer producer) throws Exception {
        return null;
    }
};

Edit 2: 编辑2:

I should probably mention that I would like to intercept those requests and read/alter content (actually only HTTP headers). 我可能应该提到,我想拦截那些请求并读取/更改内容(实际上只是HTTP标头)。 In effect I would like to implement an MITM proxy. 实际上,我想实现一个MITM代理。

Edit 3: 编辑3:

I tried replacing the target component with log to see whether the request gets through: 我尝试用log替换目标组件,以查看请求是否通过:

from("jetty:http://localhost:80?matchOnUriPrefix=true")
.to("log:test")

The message gets logged when used as a proxy with HTTP. 当用作HTTP的代理时,将记录该消息。 It also gets logged when I replace the URI with jetty:https://localhost?matchOnUriPrefix=true and try opening https://localhost directly in the browser. 当我用jetty:https://localhost?matchOnUriPrefix=true替换URI并尝试直接在浏览器中打开https://localhost时,也会记录日志。 However, when trying to use this as a proxy with HTTPS, I cannot get it to log. 但是,当尝试使用它作为HTTPS代理时,我无法使它记录下来。 It seems like the Jetty component doesn't support this behavior. 看来Jetty组件不支持此行为。 Is it correct? 这是正确的吗?

I also tried using the Netty-http component with similar results (route tracer logged the CONNECT request but the message doesn't get passed to the Log component) 我还尝试使用Netty-http组件获得类似结果(路由跟踪器记录了CONNECT请求,但消息未传递到Log组件)

The key was to define a handler for jetty that would take care of the CONNECT method: 关键是为码头定义一个处理程序,该处理程序将处理CONNECT方法:

from("jetty:http://localhost:80?matchOnUriPrefix=true&handlers=#connectHandler")

The connectHandler in this case can be either a Jetty ConnectHandler (for normal HTTPS proxies) or a custom one (for MITM proxies): 在这种情况下, connectHandler可以是Jetty ConnectHandler (对于普通的HTTPS代理),也可以是定制的(对于MITM代理):

class CustomConnectHandler extends ConnectHandler {
    @Override
    protected SocketChannel connect(HttpServletRequest request, String host, int port) throws IOException {
        SocketChannel channel = SocketChannel.open();
        channel.socket().setTcpNoDelay(true);
        channel.socket().connect(new InetSocketAddress("localhost", 443), getConnectTimeout());
        return channel;
    }
}

This one connects to port 443 on the localhost and routes SSL data there. 该端口连接到本地主机上的端口443,并在那里路由SSL数据。 So we need to define another route from there: 因此,我们需要从那里定义另一条路线:

from("jetty:https://localhost:443?matchOnUriPrefix=true")

(we can keep two separate routes or join them later by using a SEDA component) (我们可以保留两条单独的路线,或者稍后使用SEDA组件将其加入)

To define custom SSL context parameters (key store, trust store, etc.), we can use the sslContextParametersRef parameter on the endpoint. 要定义自定义SSL上下文参数(密钥库,信任库等),我们可以在端点上使用sslContextParametersRef参数。

Next, we need to alter the URL. 接下来,我们需要更改URL。 We do this by populating the URI header with the full URL (it's only the relative path by default): 为此,我们用完整的URL填充URI标头(默认情况下仅为相对路径):

.setHeader(Exchange.HTTP_URI, simple("${header.CamelHttpUrl}"))

We also need to remove the PATH header because the HTTP4 component builds the final URL by concatenating the URI and PATH headers: 我们还需要删除PATH标头,因为HTTP4组件通过连接URI和PATH标头来构建最终URL:

.removeHeader(Exchange.HTTP_PATH)

Finally, we can forward the message to the HTTP4 component. 最后,我们可以将消息转发到HTTP4组件。 We should also set throwExceptionOnFailure=false to forward errors to the client and httpClient.redirectsEnabled=false to forward redirects (this can otherwise mess with some sites): 我们还应该设置throwExceptionOnFailure=false来将错误转发给客户端,并设置httpClient.redirectsEnabled=false来转发重定向(否则可能会与某些站点httpClient.redirectsEnabled=false ):

.to("http4:dummy?throwExceptionOnFailure=false&httpClient.redirectsEnabled=false");

I hope this helps anyone who is looking to implement an HTTPS proxy using Camel and was struggling like me. 我希望这对希望使用Camel实现HTTPS代理并且像我一样挣扎的人有所帮助。

On most computer systems, localhost resolves to the IP address 127.0.0.1 在大多数计算机系统上,localhost解析为IP地址127.0.0.1

Note:- This is a valid implementation in case of using Fiddler.*** 注意:-在使用Fiddler的情况下,这是有效的实现。***

<camelContext id="context" xmlns="http://camel.apache.org/schema/spring">
    <properties>
        <property key="http.proxyHost" value="127.0.0.1"/>
        <property key="http.proxyPort" value="8888"/>
   </properties>
</camelContext>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM