Locations

A "Location" is a part of the site which matches specific attributes in the incoming request - it can be e.g. a specific hostname (virtual host), it can be based upon URL path, or even user ID or group.

For a particular location you specify how the gateway should react - should it modify the request or responses ? should it add /  remove headers or cookies, and should it forward/proxy the request to one of the configured Destinations or should it respond with a specific response or a dynamic one created by a script.

Locations can be nested, so you can have a setup similar to this:

In this example, the first location matches every request - and it just adds a Via: HTTP header to the response - the next location matches any request where the hostname matches the pattern app.* - this location does not need to do anything itself (although it can) - and once that is done, any eventual nested locations get a chance to look further at the request - in this case we have an anonymous part of the site, and a secret part, which requires specific group membership to be able to access. If neither the anonymous or the secret part is hit, the default action is to respond with an error.

Location Processing

Each configured location is processed in order, starting with the top one and going down the chain - if the specified conditions match, any eventual nested locations are processed before moving down the train.

Each location has an action, and processing terminates when a matched location results in either the Proxy or Respond action - meaning the location either proxies the request onwards to one of the configured Destinations or it responds with a specified or scripted HTTP response.
Actions can be one of continueproxyrespond or serve

Location Flags

A location has a few flags that can be set;

  • Session is needed
    The first location in the request chain (matching or not) that has this flag set causes the session resolver plugins to be executed to find a session based upon the incoming request - see Sessions and Plugins for information about session resolvers. 
  • Session will only be established if conditions match
    Creation of the session using the Session resolvers is only done if conditions for this location matches the request.
  • Override global session settings
    Allows you to specify session settings per location, e.g. if you only want some type of session resolves (such as bearer token) to be active for specific locations.
  • Preload request content
    If set, and if the request contains data, e.g. for a POST or PUT request, request content (body) is preloaded before the location is processed - this can be done if you e.g. have an authentication script that needs access to the request body, or if your Conditions look at the POST parameters in the request.
  • Compress proxied responses
    If set, and the client supports it (by sending the appropriate zip/deflate request Accept-Encoding headers) the response will be compressed when sending it back to the client, unless the destination target server has already done so itself.

Limits / Request Throttling

You can limit the number of concurrent requests, and/or the number of requests per second.

Limits can be qualified using macros, e.g. %{REMOTE_ADDR} limits concurrent requests or requests per second per IP address while %{statevariable:client_id} limits requests for a specific client_id state variable taken from the session.
Note that limits are per location, so limits per client ID for one location does not affect other locations. 

These limits are used for throttling requests - they are not denying requests if limits are exceeded. Requests are queued up unless the queue size has been exceeded.

If you want strict limits and want to deny requests if they exceed the limits, perhaps rate limiting, subscriptions etc. in the API Management will do the trick for you, please see API Management Configuration.

Any limitations are set per Gateway instance - so if you have multiple gateways running and need fixed total limits, you need to adjust your limits accordingly for each gateway.


The limits are configured using fixed number of requests per seconds - this means you cannot directly specify a limit of 10 requests for one client_id and a limit of 20 requests per second for another client_id, but you can archive this by splitting into different groups.

Imagine you have 3 different sets of Quality Of Service (QOS) type of limits you want to configure - one for basic customers, another for gold members and a 3rd for platinum members.

You can archive this by setting a Request Attribute, e.g. "rategroup" (using either a script, macro, pipeline etc.) - and after this is set, you can define 3 locations;

  • "Rate limiting basic" where you set the rate limit to 10 requests per second, and in the conditions for this location, set request attribute rategroup=basic
  • "Rate limiting gold" where you set the rate limit to 100 requests per second, and in the conditions, set the request attribute rategroup=gold
  • "Rate limiting platinum" where you set the rate limit to 1000 requests per second, and in the conditions, set the request attribute rategroup=platinum

This allows you to divide your requests into multiple groups with limits set according to the group.


Conditions

Conditions are the rules for selecting a specific location - locations are processed one at a time, top-down - any eventual nested/child locations are processed before further requests in the chain - but only if the "parent's" conditions matched the request.

Conditions can be defined on the following attributes;

  • path
    Request URI / Path - e.g. /*, /secret/* or *.png 
  • host
    Hostname  of the request, e.g. app.*, *.my.domain or login.ceptor.io
  • cookie
    Request cookie value.
  • query
    Request query parameter - /?param=value
  • postparam
    A request POST parameter sent in a URL form encoded POST request. 
  • pathparam
    A request path parameter - similar to query parameters, but separated with semicolon instead of question mark - e.g. /somepath;param=value;param2=value2 
  • method
    Request HTTP method, e.g. GET, HEAD, POST, PUT etc. 
  • scheme
    Request scheme - either http or https. 
  • header
    The value of a specific HTTP request header, e.g. the Accept header. 
  • remoteip
    The remote IP address the request originated from - note that this can be checked against not just an IP address, but a configured IP Range.
  • attribute
    A request attribute - not part of the request, but can be the result of an earlier location - request attributes can be created by a location and reused in conditions for later locations. 
  • geoip
    A specific Geo IP attribute, such as a country, ISP or city.
  • userid
    A specific user ID (note that for this information to be available, the location needs to have the "Session is needed" flag set).
  • usergroup
    A specific user group (note that for this information to be available, the location needs to have the "Session is needed" flag set).
  • script
    This allows you to create a script which can use any means to decide what conditions are required to match, it could, for example, check a time interval or do complex validation of multiple session attributes and request content.
  • macro
    Allows you to check the value of a macro, e.g. check if %{SERVER_ADDR} matches a specific IP address.
  • probability
    Specify a percentage probability of match - this enables a condition that matches a percentage of the requests, e.g. 10% - use this to send e.g. 10 or 20% of requests to a different version than the rest to allow gradual upgrades that do not affect all users.

Multiple different values can be configured for each attribute, and you can negate the expression, e.g. the condition can be matched if the attribute does NOT match a configured value.

Also, in the individual value string you can use wildcards; * and ? or the pipe sign | to specify multiple values.
you can also prefix it with {uripath} - in this mode, * will match any character except for the forward slash /. If you prefix it with {regex} then you can specify a regular expression.
When using{regex} you can optionally specify flags for regular expression matching, e.g. {regex:IGNORE_CASE} - the flags available are:

  • IGNORE_CASE 
  • UNIX_LINES
  • COMMENTS
  • LITERAL
  • MULTILINE
  • DOTALL
  • UNICODE_CASE
  • CANON_EQ
  • UNICODE_CHARACTER_CLASS

Please refer to Oracle's Java documentation for the individual flags and their meaning here: https://docs.oracle.com/javase/tutorial/essential/regex/pattern.html 


Conditions are very powerful - as an example, if you configure an IP range and set it up to load data periodically from an IP reputation database, you can set up a location with a condition where the remoteip matches the IP range.

Then you can take action on the request originating from a known spammer, tor exit node, anonymizer, malware spreader, attacker or spammer.

Action could include:

  • Denying all traffic from known "bad" clients
  • Limiting concurrent requests or requests per second, scaling down service provided to known bad addresses.
  • Require additional authentication, e.g. two-factor before accepting requests.


Invalid Session Action

If a session is invalid, e.g. a session cookie contains a session that is timed out, you can respond with an error message, redirect to another URL or you can continue on with a new anonymous session.

The "Invalid Session Action" controls what to do in which case.

Nested Locations

Locations can be nested, so if a match is found for this location, and its action is "continue" then processing will continue with any matching nested sessions that might exist.

Response Hooks

Response hooks allow you to easily hook into specific HTTP responses and change them or do something specific based upon then - e.g. instead of sending a 401 response back, you can redirect to a login page.
You can also change the HTTP status code or modify HTTP headers before they are being processed by the gateway.

URL Validation

The incoming request URL can be validated both for correct encoding and for valid characters as well as maximum lengths of either the complete URL or any individual query parameters.
Additionally, hostname and domain can optionally be validated to ensure it is correct according to IANA verified top-level domains.

Parameter Validation

Allows you to validate path, query and POST parameters in the request - you can specify valid key / name patterns and valid value patterns and regular expressions to validate all input parameters.
In case validation fails, you can specify what action to take, such as returning an error message.
You can use this to defend against e.g SQL Injection attacks by limiting the acceptable input characters. 

URL Rewrite

URLs can be rewritten before processing is continuing with the rewritten URL - both scheme, hostname and path can be changed.
When rewriting URLs, you can use regular expressions, and e.g. rewrite from ^/TOPSECRET/(.*) to /secret/$1 - this will change an incoming URL /TOPSECRET/sample to /secret/sample. You can also apply specific conditions to each URL Rewrite expression so it is only done in case the listed conditions match.

IP Change Restriction

By default, clients are not allowed to change IP address during their session, this means that the requests will fail if the user changes IP address mid-session. But, you can allow this (for individual or all locations) either by using GeoIP location information, and e.g. allow clients to change IP address within the same country, same ISP or same city or even with a given distance to the original IP.
You can also define complex matching rules, where you e.g. allow change of country between specific known countries, e.g. Denmark and Sweden, or you can define a script which can determine if it allows the change or not based upon full request and session content.

In addition to using GeoIP you can specify a number of ranges where IP switching is allowed within a range - e.g. any IPs within the 192.168.1.0/30 range.

Note that IP checking is only done for a location if a session is available - if the "Session is needed" flag is turned off, no validation is done, since no original IP address is known. If you want to protect a location so it is only available for a specific set of IP addresses, consider using IP restrictions in location instead of IP Change Restriction instead.

Authentication

For each location, you can specify a form of Authentication that is supported - for each authentication type, you can specify if it is required or not, and what to do if that particular sort of authentication information is not provided.

Ceptor Gateway is currently provided with the following Authentication Plugins; (see the Plugins section for additional information).

  • Forms
  • Basic Authentication
  • SPNEGO
  • NTLM
  • SSL Client Certificate
  • OpenID Connect
  • WebSSO

Typically, you use the Gateway for transport-level authentication, and use either Forms authentication or another Location to redirect to a Destination Server which is reachable anonymously - in that, you can provide advanced authentication dialog with the user, e.g. for NemID Login, or Two-Factor authentication - the application then has the dialog with the user until he is authenticated and redirects back to the original location when authentication has completed.

Authorization

You can configure the Gateway to do Authorization checking for a given location - in here, you can specify the list of valid HTTP methods. You can specify a list of one or more roles where at least one of them are required for the user to have access. You can use the following magic role names;

  • pp_everyone
    Matches all users with a valid session.
  • pp_anonymous
    Matches all anonymous users which have not yet logged in.
  • pp_identifiedusers
    Matches all identified users, no matter how they are identified and which roles they have. 

You can also specify a server identifier - if done, the configured Authorization plugins in the Ceptor Session Controller will be called - they can provide a list of protected URLs for a given server identifier, and the URLs will be checked against this list also.

Lastly, you can specify a script to run to do more detailed authorization checking based upon all information in the request and the session, as an example this scripts denies access if the Content-Type header in the request contains the string "YouShallNotPass" but allows access otherwise.

if (state.httpExchange.getRequestHeaders().getFirst('Content-Type') == 'YouShallNotPass')
  false;
else
  true;

Note that to gain authorization, all defines checks has to pass, meaning both the listed roles / groups, the URLs from the authorization plugin, and the script must all allow authorization or it will fail. For failed authorization checks, you can specify what to happen, e.g. redirect to another URL, send back an error page or JSON error structure based upon the request Accept header.

Request Attributes

A location can set request attributes which can be used within conditions by other locations, or they can be accessed by scripts that are run later in the request processing flow. The value of each individual attribute can be set to either a macro or a script.

Request Headers

You can specify a list of HTTP headers that are added to the request before processing continues. Refer to Scripts and Macros for information on the possibilities on how to specify values as scripts and/or macros.

Any value that results in an empty string, or a script that returns null means that the header will be removed from the request.

By combining this with Location Conditions, you could e.g. create a location which in its condition has a group called pp_identifiedusers - this means that it will be processed for all identified users. In this Location, you can leave the action as "continue", and add the Request Header "AuthenticatedUser" with the value "%{REMOTE_USER}", and another header called "AuthenticatedGroups" with the value "%{SESSION_GROUPS}".

This will then add two HTTP headers to any requests later being proxied to a Destination; AuthenticatedUser and AuthenticatedGroups with respectively the userid and a comma-separated list of usergroups.

Request Cookies

Like with specifying HTTP request headers, you can add request cookies to the request here - here, you can e.g. delete the sessionid / sslsessionid cookies that contained the original session ID if you do not want to proxy this on to Destinations or you can add other cookies and values based upon request or session content.

Response Headers

You can specify a list of HTTP headers that are added to the response when it is sent back to the client. Refer to Scripts and Macros for information on the possibilities on how to specify values as scripts and / or macros.

Response Cookies

You can specify a list of reply cookies that are added to the response when it is sent back to the client. Refer to Scripts and Macros for information on the possibilities on how to specify values as scripts and / or macros.
This feature can also be used to modify existing cookies, e.g. to add httpOnly / secure flag, path or domain to them.

Note that while rules for request headers are processed sequentially starting with the first location, the sequence is reversed for response headers and cookies, so if you have locations A, B and C, and each has rewrite rules for both request and response headers, request headers will be processed in sequence A, B, C while response headers and cookies will be processed as C, B, A.

Canned Responses

Canned Responses are responses that can be defined and reused from multiple different locations - where you reuse it, you can override specific parts of the response, such as status code, reason or HTTP headers.

WebServer

If action is set to serve then the gateway can serve static resources, e.g. images, stylesheets, javascript or html files. This allows you to reference static resources from responses, e.g. error pages and serve them directly for the gateway.


© Ceptor ApS. All Rights Reserved.