Implementing Apache’s force proxy flag for rewrite rules under NGINX

NGINX’s default behavior for rewrite rules (at least up to version 0.7.65) is to redirect if the replacement part begins with ‘http://’. Let me quote some info from NGINX’ wiki:

rewrite

syntax: rewrite regex replacement flag

[...]

If the replacement string begins with http:// then the client will be redirected, and any further rewrite directives are terminated.

It is important to take this into consideration while designing new rules because the behavior of the rule itself is bound to the place we are retrieving data from.

Apache does this differently since it offers a flag that can be set per rule which instructs the web server to just “proxy” the request (i.e. do not redirect, just get the response of that request in the background and send it back to the client). Taken from Apache’s site, this flag is:

proxy|P‘ (force proxy)
This flag forces the substitution part to be internally sent as a proxy request and immediately (rewrite processing stops here) put through the proxy module. You must make sure that the substitution string is a valid URI (typically starting with http://hostname) which can be handled by the Apache proxy module. If not, you will get an error from the proxy module. Use this flag to achieve a more powerful implementation of the ProxyPass directive, to map remote content into the namespace of the local server.

Note: mod_proxy must be enabled in order to use this flag.

How to implement this under NGINX

I have been able to get similar behavior under NGINX using ‘rewrite’ and ‘proxy_pass’ directives.

The following example implements a regular expression based rewrite rule serving content from domain2 to the client’s request on domain1.

Using that NGINX configuration, the client can request:

which will be proxied to:

and served back to her “apparently” from http://domain1.com/12/34/test (i.e. there won’t be any URL redirection).

http_load man page

How to test CAS’ SAML using soapUI

Overview
Recent versions (I believe 3.2 or older) of Central Authentication System (a.k.a. CAS) include Security Assertion Markup Language (a.k.a. SAML) support, out of the box. The beauty if it is that it is already “there” accessible through the URL ‘/cas/samlValidate’ instead of the usual ‘/cas/serviceValidate’.

One thing to be noted is that it is not so easy to communicate with your CAS instance using SAML protocol since the requests need to be HTTP POST (which put browsers out of the picture) using a properly formed SAML payload.

Here is when soapUI comes in, which is an excellent tool for web services testing using SOAP requests (there should not be any problem/limitation by using the open source version of the tool) since it can be used to complete the SAML communication and see what the CAS server is actually returning back.

Steps
So, in order to complete that, you would need to connect to your CAS server, login by providing valid credentials and then get a CAS ticket. This can be done by opening the following URL on a browser:

The browser should be now displaying an error because it should have been redirected back to the URL http://localhost/foo which probably does not exist. No problem. What is important though is that you would be able to retrieve the ticket from the URL. Example:

Now using SoapUI you need to send CAS a proper SAML request. You may do that using the “submit a request to a specified end point” action. The URL where to send the request should be:

the request body should be:

CAS’ response should be similar to this:

The returned username can be found in the ‘NameIdentifier’ tag. You may find here a soapUI real screenshot to make things clearer:

soapUI screenshot

Click here to the the screenshot in FULL SIZE.

See Also

Note.- special thanks to Juan Huerta, Julien Gribonvald and Marvin Addison for their tips which inspired me to write this post.

KeepAlived Installation under Debian Etch

Briefly, KeepAlived is a daemon that is able to provide failover capabilities to servers/services by binding virtual IP addresses to machines. In the event of failure, KeepAlived would reassign this virtual IP to another machine. This action is executed fast (less than 2 seconds) and automatically.

This is a very interesting daemon to be used in combination with HAProxy, for example. It would be possible to have a failovered load balancer. In the event of this load balancer failing, keepalived would switch to another that is up and running in such a clean and fast way that the clients would not notice.

Installation steps under Debian Etch

The system will ask a couple of questions. I usually reply using the default values, then configure myself manually the daemon, by editing /etc/keepalived/keepalived.conf.

To make the virtual IP address bindable, you should add this line /etc/sysctl.conf:

Check binding:

It is convenient to alter the order when keepalived is being started upon restarts. We probably want to have it started at the end so all the services are already running by the time keepalive runs. To do that:

See Also

Sticky sessions (aka persistence)

While working with load balancers it is sometimes required that the client connects to the same backend server all the time. This concept has several names (e.g.: sticky sessions, session stickiness, persistent sessions, persistence, etc…).

Wikipedia explains this concept clearly:

One dilemma when operating a load-balanced service, is what to do if the backend servers require some information (“state”) to be stored “persistently” (across multiple requests) on a per-user basis. This can be a problem if a backend server needs access to information generated by a different backend server during a previous request. Performance may suffer if cached information from previous requests is unavailable for re-use.

One solution is to consistently send clients to the same backend server. This is known as “persistence” or “stickiness”. One downside to this technique is lack of automatic failover, in case one or more backend servers should fail or be taken offline for maintenance. Persistent information is lost if it cannot be transmitted to the remaining backend servers. Citation.

See Also