Network Filters

What is a Filter?

A filter is a mechanism for plugging into the low-level TCMP stream protocol. Every message that is sent across the network by Coherence is streamed through this protocol. Coherence supports custom filters. By writing a filter, the contents of the network traffic can be modified. The most common examples of modification are encryption and compression.

Standard Filters

Compression Filter

The compression filter is based on the java.util.zip package and compresses message contents thus reducing the network load. This is useful when there is ample CPU available but insufficient network bandwidth. See the configuration section for information on enabaling this filter.

Encryption Filters

Coherence ships with two JCA based encryption filters which can be used to protect the custered communications for privacy and authenticity.

Symmetric Encryption Filter

This filter uses symmetric encryption to protect cluster communications. The encryption key is generated from a shared password known to all cluster members. This filter is suitable for small deployments or where the maintenance and protection of a shared password is feasible.

To enable this filter specify which services will have their traffic encrypted via this filter, or to enable it for all cluster traffic you may simply specify it as a filter for the <outgoing-message-handler> element.

<outgoing-message-handler>
  <use-filters>
    <filter-name>symmetric-encryption</filter-name>
  </use-filters>
</outgoing-message-handler>

The shared password may either be specified in the <filters> section of the operational configuration file, or via the tangosol.coherence.security.password system property, see the Symmetric Encryption Filter Parameters section for additional configuration options.

PKCS Encryption Filter

This filter uses public key cryptography (asymmetric encryption) to protect the cluster join protocol, and then switches over to much faster symmetric encryption for service level data transfers. Unlike the symmetric encryption filter, there is no persisted shared secret. The symmetric encryption key is randomlly generated by the cluster's senior member, and is securly transfer to authenticated cluster members as part of the cluster join protocol. This encyrption filter is suitable for deployments where maintenance of a shared secret is not feasable.

This filter requires the JVM be configured with a JCA public key cryptography provider implementation such as Bouncy Castle, which supports asymmetric block ciphers. See the JCA documentation for details on installing and configuring JCA providers.

In the default setup each cluster node must be configured with a Java Keystore from which it may retrieve its identity Certificate and associated private key, as well as a set of trusted Certificates for other cluster members. You can consturct this keystore as follows:

Create a Java Keystore and the local cluster member's password protected certificate and private key.

keytool -genkey -alias local -keypass secret -keyalg rsa -storepass secret -keystore ./keystore.jks

Export this public certificate for inclusion in all cluster members keystores.

keytool -export -alias local -keypass secret -storepass secret -keystore ./keystore.jks -rfc -file local.cert

Import the Certificates of other trusted cluster members. Each certificate must be stored under a unique but otherwise unimportant alias.

keytool -import -alias remote_1 -storepass secret -keystore ./keystore.jks -file local_1.cert
keytool -import -alias remote_2 -storepass secret -keystore ./keystore.jks -file local_2.cert
keytool -import -alias remote_3 -storepass secret -keystore ./keystore.jks -file local_3.cert

At this point you will have one keystore per cluster node, each containing a single private key plus a full set of trusted public certificates. If new nodes are to be added to the cluster the keystores of all existing nodes must be updated with the new node's certificate.

You may also choose to supply custom key and trust management logic to eliminate the need for a full keystore per node. See the implementation's documentation for details on customization.

Then configure the cluster to encrypt all traffic using this filter by specifying it in the <outgoing-message-handler>.

<outgoing-message-handler>
  <use-filters>
    <filter-name>pkcs-encryption</filter-name>
  </use-filters>
</outgoing-message-handler>

The keystore and alias password may either be specified in the <filters> section of the operational configuration file, or via the tangosol.coherence.security.password system property, see the PKCS Encryption Filter Parameters section for additional configuration options.

Note unlike the Symmetric Encryption Filter, this filter is not currently supported by Coherence*Extend, or on a service by service level.

Configuring Filters

There are two steps to configuring a filter. The first is to declare the filter in the <filters> XML element of the tangosol-coherence.xml file:

<filter>
  <filter-name>gzip</filter-name>
  <filter-class>com.tangosol.net.CompressionFilter</filter-class>
  <init-params>
    <init-param>
      <param-name>strategy</param-name>
      <param-value>gzip</param-value>
    </init-param>
  </init-params>
</filter>

For more information on the structure of the <filters> XML element of the tangosol-coherence.xml file, see the documentation in the coherence.dtd file, which is also located inside coherence.jar.

The second step is to attach the filter to one or more specific services, or to make the filter global (for all services). To specify the filter for a specific service, for example the ReplicatedCache service, add a <filter-name> element to the <use-filters> element of the service declaration in the tangosol-coherence.xml file:

<service>
  <service-type>ReplicatedCache</service-type>
  <service-component>ReplicatedCache</service-component>
  <use-filters>
    <filter-name>gzip</filter-name>
  </use-filters>
  <init-params>
    ...
  </init-params>
</service>

To add the filter to all services, do the same under the <outgoing-message-handler> XML element instead of under a <service> XML element:

<outgoing-message-handler>
  <use-daemon>false</use-daemon>
  <use-filters>
    <filter-name>gzip</filter-name>
  </use-filters>
</outgoing-message-handler>

Filters should be used in an all-or-nothing manner: If one cluster member is using a filter and other is not, the messaging protocol will fail. You should stop the entire cluster before configuring filters.

Creating a Custom Filter

To create a new filter, create a Java class that implements the com.tangosol.io.WrapperStreamFactory interface and optionally implements the com.tangosol.run.xml.XmlConfigurable interface. The WrapperStreamFactory interface provides the stream to be wrapped ("filtered") on input (received message) or output (sending message) and expects a stream back that wraps the original stream. These methods are called for each incoming and outgoing message.

If the filter class implements the XmlConfigurable interface, then Coherence will configure the filter after instantiating it. For example, consider the following filter declaration in the tangosol-coherence.xml file:

<filter>
  <filter-name>my-gzip-filter</filter-name>
  <filter-class>com.tangosol.net.CompressionFilter</filter-class>
  <init-params>
    <init-param>
      <param-name>strategy</param-name>
      <param-value>gzip</param-value>
    </init-param>
    <init-param>
      <param-name>buffer-length</param-name>
      <param-value>1024</param-value>
    </init-param>
  </init-params>
</filter>

If the filter is associated with a service type, every time a new service is started of that type, Coherence will instantiate the CompressionFilter class and will hold it with the service until the service stops. If the filter is associated with all outgoing messages, Coherence will instantiate the filter on startup and will hold it until the cluster stops. After instantiating the filter, Coherence will call the setConfig method (if the filter implements XmlConfigurable) with the following XML element:

<config>
  <strategy>gzip</strategy>
  <buffer-length>1024</buffer-length>
</config>