http to https using membrane service proxy rewriter

249 views
Skip to first unread message

Noel

unread,
Aug 15, 2017, 12:25:32 AM8/15/17
to membrane-monitor
I am attempting to use membrane service proxy v4.4.2 as _forward_ proxy for a set of client systems, using the rewriter directive to rewrite some or all http requests to https.  I'm attempting this based off the rewrite documentation at https://www.membrane-soa.org/service-proxy-doc/3.5/configuration/reference/rewriter.htm .

The proxy.xml that I'm using has the following (example.com substituting for the domain I'm needing to rewrite for):

        <router>
                <serviceProxy ip="127.0.1.1" port="8081">
                        <rewriter>
                                <map from="^http://(.*).example.com/(.*)$" to="https://$1.example.com/$2" />
                                <map from="^http://(.*).my.example.com/(.*)$" to="https://$1.my.example.com/$2" />
                        </rewriter>
                </serviceProxy>
        </router>


I also tried a simpler configuration to just rewrite everything:

        <router>
                <serviceProxy ip="127.0.1.1" port="8081">
                        <rewriter>
                                <map from="^(.*)$" to="https://$1" />
                        </rewriter>
                </serviceProxy>
        </router>

In either case, when I attempt to connect through the proxy, I get the following NullPointerException:

WARN AbstractHttpHandler:89 - An exception occured while handling a request:
java.lang.NullPointerException
    at com.predic8.membrane.core.util.URLUtil.getPathQuery(URLUtil.java:24)
    at com.predic8.membrane.core.interceptor.rewrite.RewriteInterceptor.handleRequest(RewriteInterceptor.java:156)
    at com.predic8.membrane.core.interceptor.InterceptorFlowController.invokeRequestHandlers(InterceptorFlowController.java:106)
    at com.predic8.membrane.core.interceptor.UserFeatureInterceptor.handleRequest(UserFeatureInterceptor.java:43)
    at com.predic8.membrane.core.interceptor.InterceptorFlowController.invokeRequestHandlers(InterceptorFlowController.java:106)
    at com.predic8.membrane.core.interceptor.InterceptorFlowController.invokeHandlers(InterceptorFlowController.java:71)
    at com.predic8.membrane.core.transport.http.AbstractHttpHandler.invokeHandlers(AbstractHttpHandler.java:70)
    at com.predic8.membrane.core.transport.http.HttpServerHandler.process(HttpServerHandler.java:234)
    at com.predic8.membrane.core.transport.http.HttpServerHandler.run(HttpServerHandler.java:119)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)


I've also tried various incarnations of the <ssl> directive, but it seems to only work with a <target>The use case appears to be similar to the one described at https://www.membrane-soa.org/service-proxy-doc/4.4/ssl-termination-tunneling.htm as "SSL Tunnel to server" but the example in examples/ssl-client/proxies.xml specifies a target, and I need a more generic rewrite of incoming URLs from http to https, not directing all traffic to a specific site.

What am I doing wrong here, and is there a way to do what I want with membrane?

-Noel

Tobias Polley

unread,
Aug 15, 2017, 12:43:41 AM8/15/17
to membrane-monitor
Hi Noel,

the rewriter only acts on the URI's path. What you are trying to do is therefore not possible using the rewriter.
We use

<serviceProxy host="foo.de">
    <rewriter><map from="/(.*)" to="https://bar.de/$1" /></rewriter>
</serviceProxy>

to redirect traffic to some HTTPS site.
For your use case, one would need to write groovy code.

Best
Tobias

Ron

unread,
Jan 14, 2018, 12:16:19 PM1/14/18
to membrane-monitor


Hi Tobias et al,

Attempting to write a Groovy script for a s similar use-case,  we are encountering difficulties understanding the necessary script operation.

It seems that the Groovy script gains access to an Exchange and through, it, the request.
But apparently, both of these contain just the path of the request URI, and no http:// ot https:// part.

Could you please clarify,

-  how to distinguish in Groovy between a http and a https call?    (for rewriting the former to the latter)

and,

- which API call to make on the Exchange to modify the protocol (same host/path) and proceed?

Thanks so much for your help!

Ron

Tobias Polley

unread,
Jan 16, 2018, 12:10:04 PM1/16/18
to membrane-monitor
Hi Ron.



Attempting to write a Groovy script for a s similar use-case,  we are encountering difficulties understanding the necessary script operation.

It seems that the Groovy script gains access to an Exchange and through, it, the request.
But apparently, both of these contain just the path of the request URI, and no http:// ot https:// part.

The Java classes are very protocol-oriented. In HTTP or HTTPS requests, usually no complete URLs are submitted at the protocol level.
 

Could you please clarify,

-  how to distinguish in Groovy between a http and a https call?    (for rewriting the former to the latter)

There is a way, as shown below. Note though, that you rarely need it, as you already have to specify multiple <serviceProxy>s (and therefore, as shown in the example, probably already have multiple <groovy> interceptors) to distinguish between SSL ports and non-SSL ports.

<serviceProxy port="443">
<ssl>
<keystore location="../router/conf/membrane.jks" password="secret" keyPassword="secret" />
<truststore location="../router/conf/membrane.jks" password="secret" />
</ssl>
<groovy>
import com.predic8.membrane.core.rules.SSLableProxy
if ((exc.rule instanceof SSLableProxy) &amp;&amp; ((SSLableProxy) exc.rule).getSslInboundParser() != null) {
println "this has SSL/TLS"
} else {
println "this has no SSL/TLS"
}
</groovy>
<target host="thomas-bayer.com" />
</serviceProxy>

<serviceProxy>
<groovy>
import com.predic8.membrane.core.rules.SSLableProxy
if ((exc.rule instanceof SSLableProxy) &amp;&amp; ((SSLableProxy) exc.rule).getSslInboundParser() != null) {
println "this has SSL/TLS"
} else {
println "this has no SSL/TLS"
}
</groovy>

<rewriter><map from="/(.*)" to="https://localhost/$1" /></rewriter>
</serviceProxy>

 

and,

- which API call to make on the Exchange to modify the protocol (same host/path) and proceed?

Usually, the switch from non-SSL to SSL (or vice versa) is done as shown in the example ssl-client (or ssl-server, respectively).

However, as this does not cover all use cases, it can, of course, been done programmatically as well: 1) specifying no <ssl/> within the <target/>, 2) setting (or not setting) the SSL_CONTEXT property on the exchange and 3) changing the schema of the destination URL.

<router id="router">

<serviceProxy>
<groovy>
import com.predic8.membrane.core.transport.ssl.StaticSSLContext
import com.predic8.membrane.core.config.security.SSLParser

def router = spring.getBean("router")

exc.setProperty("SSL_CONTEXT", new StaticSSLContext(new SSLParser(), router.getResolverMap(), router.getBaseLocation()))
exc.getDestinations().clear();
exc.getDestinations().add("https://www.predic8.de");
</groovy>

<target host="www.predic8.de" />
</serviceProxy>

</router>

Best, Tobias

ron....@experitest.com

unread,
Jan 17, 2018, 9:48:56 AM1/17/18
to membrane-monitor

Thanks Tobias, we'll try this.  Incidentally, all our configuration is programmatic.

All the best,

Ron


On Tuesday, January 16, 2018 at 7:10:04 PM UTC+2, Tobias Polley wrote:
Hi Ron.

.....
Reply all
Reply to author
Forward
0 new messages