# Secure DMZ adapter

# Introduction

The secure DMZ adapter serves as a proxy for a DMZ (demilitarized zone), which analyzes requests to the 4ALLPORTAL and blocks or transfers the data to the internal network. It is an Java application including an embedded Jetty server which must be installed in the DMZ.

In each response, the header Server: DMZ Adapter is set.

Possible restrictions are:

  • URL
  • blocking of calls with an invalid session
  • blocking of logins after too many attempts

The following requests can be made:

  • HTTP/HTTPS requests
  • video streaming
  • file upload
  • file download
  • AMF (Action Message Format) requests

The session of a request can be checked, so that requests with an invalid session will not be forwarded. If the access to a resource is rejected, the HTTP status code 403 (forbidden) is sent.

# Supported DAM version

This documentation implies an installed DAM version 3.4 or higher.

# Download package

You can download the dmz-adapter.zip needed for installation from admin snap-in General system configuration/App management/DMZ adapter.

# Clustering

The DMZ adapter does not cluster. Cookies are transferred though, so that clustering is possible via a downstream service (e.g. Apache).

# Multipart requests

If you use multipart requests, only the session from a cookie can be checked. If no cookie is set, the analysis in the DMZ will not take place.

Reading out the session from a multipart request does not work, for the request was consumed and can thus no longer be forwarded.

# Requirements

  1. The DMZ server and the DAM must be approached via the same URL. A different URL would cause problems with various functions, especially when sending e-mails which link to the DAM:
    • welcome e-mail
    • change of password
    • sending an eTicket
    • ...
  2. On the DMZ server a host entry must be set to the DAM URL of the DAM server.
  3. A 64-bit JavaSDK (Java version 11 or higher) must be installed.
  4. If you use Windows: The JRE_HOME must be set to the correct Java installation. Otherwise, the Windows service will not work.

# Installation and configuration

Unpack dmz-adapter.zip into e.g. C:\\Program Files\\4AllPortal\\dmz or /usr/local/4AllPortal/dmz.

# Customize configuration

Configure the DMZ adapter in the file dmz-adapter.xml.

  1. http_port: Customize or set to empty if you want to disable.
  2. https_port: Set if required.
  3. server_name: Define host for which the proxy configuration works. Only requests with this URL will be processed.
  4. server_alias (optional): Define additional hosts which will be processed.
  5. dam_url: AMF URL to DAM. Required to read the session. Example: http://example.4allportal.net:8181/service/amf
  6. target: URL to which the request should be forwarded to (DAM URL). Example: https://example.4allportal.net/
  7. redirect_http: Set enable to true if all http pages should be requested via https. http_port must be configured.
  8. SSL: Set enable to true, if SSL (incoming) should be supported. For further information, see https.

# Windows service

To run as a service on Windows, the commons-daemon/procrun is used. Set variables in the file install_service.cmd:

variable description example
DMZ_ADAPTER_HOME path to DMZ adapter C:\Program Files (x86)\4AllPortal\dmz
JRE_HOME path to JRE. If not set, use system JRE. C:\Program Files\Java\jdk-14.0.1
StartParams path to dmz-adapter config "--config-file C:\Program Files (x86)\4AllPortal\dmz\conf\dmz-adapter.xml"
  • execute: install_service.cmd
  • start the service: start_service.cmd
  • delete the service: sc delete dmz-adapter

# Linux service

# Service definition for Centos / RedHat - systemd service

To use the systemd service, create the file /etc/systemd/system/dmz-adapter.service and set valid values.

Example:

    [Unit]
    Description=4AllPortal DMZ Adapter
    [Service]
    WorkingDirectory=/usr/local/4AllPortal/dmz/
    ExecStart=/usr/bin/java -jar /usr/local/4AllPortal/dmz/dmz-adapter.jar  --config-file=/usr/local/4AllPortal/dmz/conf/dmz-adapter.xml
    Restart=always
    RestartSec=0
    #User=1010
    LimitNOFILE=40000
    LimitNPROC=40000

    [Install]
    WantedBy=multi-user.target

# Service definition for Centos / RedHat - init.d

You can find the old configuration in file dmz-proxy in folder /etc/init.d. This will still work, but probably needs to be updated later.

# Start the DMZ adapter manually

Simply execute java -jar dmz-adapter.jar.

For debugging execute java -Xdebug -Xrunjdwp:transport=dt_socket,address=8585,server=y,suspend=n -jar dmz-adapter.jar.

# Start parameters

Use dmz-adapter plus the following options:

options description
--config-file <arg> Path to config file. If not set, use conf/dmz-adapter.xml.
--ssl-info Display infos: enabled/supported protocols and enabled/supported CipherSuites.
--help Display this help and exit.
--pause <arg> Wait for given seconds. Allow to start remote debugger.
--version Display version information and exit.

# Start the DMZ adapter via docker-compose

First, create a docker-compose file.

Example :

version: '3'
services:
  app:
    image: registry.4allportal.net/4allportal/miscellaneous/dmz-adapter:2.0.3
    restart: always
    environment:
      HTTP_PORT: 8080
      SERVER_NAME: "localhost"
      DAM_URL: "http://localhost:8383/service/amf"
      TARGET: "http://localhost:8383/"
    ports:
      - 8080:8080

Specify the environment-section of the configuration with the following variables:

  • HTTP_PORT
  • HTTPS_PORT
  • LISTEN_HTTP_PORT
  • LISTEN_HTTPS_PORT
  • SERVER_ALIAS
  • SERVER_NAME
  • DAM_URL
  • TARGET
  • DEBUG(can be either true or false and runs internally on port 8001)

After that you have to bind the ports. In case DEBUG is disabled, there is no need to bind the debug port.

Finally, run the command docker compose up to start the DMZ adapter.

# Further configuration

In case you want to do further configuration, you have to copy the conf folder under /4allportal/dmz-adapter/conf to your local machine.

Example: docker cp container-id:/4allportal/dmz-adapter/conf

Now edit the dmz-adapter.xml configuration and mount it to the docker-compose.

Example:

version: '3'
services:
  app:
    image: registry.4allportal.net/4allportal/miscellaneous/dmz-adapter:2.0.3
    restart: always
    environment:
      HTTP_PORT: 8080
      SERVER_NAME: "localhost"
      DAM_URL: "http://localhost:8383/service/amf"
      TARGET: "http://localhost:8383/"
    ports:
      - 8080:8080
    volumes:
      - "./conf:/4allportal/dmz-adapter/conf"

Important: Use the latest release version instead of 2.0.3.

# Functions of the DMZ adapter

# HTTP

To process HTTP requests, you only need to set the port. If http and a redirection to https are not supported, the value can be set to empty.

<http_port>80</http_port>

# Listen HTTP

To listen for http requests on a different port than the request port, set this: If not set, uses the same as http_port.

<listen_http_port>8080</listen_http_port>

# HTTPS

SSL/HTTPS is supported both inbound and outbound.

# Inbound

To enable HTTPS, the port must be set:

<https_port>443</https_port>

To enable SSL, the path to the keystore and the passwords for keystore and keymanager must be configured. Is also possible to deactivate protocols and ciphers here. In the following example all CBC based ciphers will be disabled.

Example:

<ssl enable="true">
   <key_store_path>ssl/keystore.jks</key_store_path>
   <key_store_password>123456</key_store_password>
   <key_manager_password>123456</key_manager_password>

   <exclude_protocols>
     <string>NOT_EXISTING</string>
   </exclude_protocols>

   <exclude_cipher_suites>
     <string>^.*_(CBC)_.*$</string>  <!-- deactivate all CBC cipher -->
     <string>TLS_DHE.*</string>
     <string>TLS_EDH.*</string>
   </exclude_cipher_suites>

</ssl>

Note: If all CBC based ciphers are disabled, SSL will not work with Safari 9.

If all HTTP requests should be redirected to HTTPS, set the HTTP port and activate redirect:

<http_port>80</http_port>
<redirect_http enable="true" />

The necessary certificates including the private key must be imported to the keystore. The certificates must be stored under an alias in the following order:

  • server certificate
  • intermediate certificate(s)
  • private key

Example:

# convert server certificate to pem
openssl x509 -in 4allportal.net.crt -out 1.pem -outform PEM
# convert intermediate certificate to pem
openssl x509 -in DigiCertCA.crt -out 2.pem -outform PEM

# convert private key (copy rear part with Vim to text file 4ap.key)
openssl rsa -text -in 4allportal.net.key -inform DER

# create bundle.pem
cat 1.pem 2.pem > bundle.pem
cat 4ap.key >> bundle.pem

# export certificate for Java
openssl pkcs12 -export -in bundle.pem -inkey 4ap.key -out 4allportal.net.p12

# generate keystore
keytool -importkeystore -srckeystore 4allportal.net.p12 -srcstoretype PKCS12 -destkeystore keystore.jks -deststoretype JKS

# check if certificates are in keystore
keytool -list -v  -alias 1 -storepass 123456 -keystore keystore.jks
keytool -list -rfc  -alias 1 -storepass 123456 -keystore keystore.jks

# Outbound

If SSL should work outbound, the necessary certificates must be installed in the operating system. This is always necessary if one of the following URLs starts with https:

  • dam_url
  • target

Insert the required certificates of the certificate chain into the file cacerts of the used java version.

Example:

       keytool -importcert -file server.crt -cacerts -alias "DMZ-lobdevelop.4allportal.net"

# Listen HTTPS

To listen for https requests on a different port than the request port, set this: If not set, uses value from https_port.

<listen_https_port>8443</listen_https_port>

# Session validation

Activate the session validation like this:

<check_4apsession>true</check_4apsession>

The system tries to read the session ID from the session cookie. If no cookie is set, the session ID is read from the request. For endpoints with checkAuthorization true, also sessions from bearer authorization will be checked (see here). The DMZ adapter checks whether data for this session is already available. If not, it tries to get the data for the session from the DAM database.

If there is a valid session, the request will be forwarded. Otherwise, the request will be rejected.

Each time a session is accessed, the access time is stored, regardless of whether the session is valid or not. All sessions that have expired and have not been accessed for a certain time will be removed from the container. The time can be configured like this:

<remove_session_after_minutes>60</remove_session_after_minutes>

# Logout

If a logout method is executed, the session in the container will be set to expired. Logout methods are:

  • /service/usermanagement/logout
  • LoginRemoteService.logoutUser (AMF)
  • /api/auth/logout

In order to be able to block further calls of expired or invalid sessions, an expired session will not be removed directly.

# Limitation of login requests

The login requests can be restricted by the host. For this, the DMZ adapter must have access to the client IP. You can configure the limitation like this:

<restrict_login enable="true">
   <after_logins>50</after_logins>
   <tries>3</tries>
   <remove_older>10</remove_older>
</restrict_login>
description
enable Set true to activate the limitation function.
after_logins Defines after how many logins the limitation is activated.
tries Defines how many logins per minute are allowed if the number set in after_logins is exceeded.
remove_older Removes logins which are older than X minutes.

Note: If access to the client IP is not possible, restrict_login must be disabled (set enable to false).

# Caching

To enable caching, you need to configure like this:

<caches enable="true" time_to_live="60">
  <cache>/fonts/*</cache>
  <cache>/4allportal-core/*</cache>
  <cache>/4allportal-essentials/*</cache>
  <cache>/4allportal-dam/*</cache>
</caches>
type required? description
enable XML attribute no (default: true) Allows you to disable the cache.
time_to_live XML attribute no (default: 60) Defines how many minutes the data will remain in the cache.
cache XML element yes Defines which calls are cached. .../* defines that all sublevels are cached, otherwise, only the exact page will be cached.

# Delete request and response headers

Deleting the request header Accept-Encoding makes it possible to e.g. deactivate compression. You can configure it like this:

<remove_request_header>
  <header>Accept-Encoding</header><!-- deactivate compression -->
</remove_request_header>

<remove_response_header>
  <header>...</header>
 </remove_response_header>

All headers set in <header> will be removed.

# Reloading

This method allows the configuration to be reloaded. This is only allowed for calls via localhost:

localhost/reload

Reloading works for:

  • endpoints
  • log_level
  • dam_url
  • cache clearing (If files are locked, a log entry will be created.)

Reloading works not for configurations like:

  • parameters of the connection like: ports, timeouts, server name
  • remove_session_after_minutes
  • restrict_login

# Checking the configuration

This method allows to check the configuration. This is only allowed for calls via localhost:

localhost/reload?only_check=true

# Logging and access log

Two files are created in the logs folder for each day:

  • log_yyyymmdd.log
  • access_yyyymmdd.log

The log level for the file log_yyyymmdd.log can be configured in the configuration file:

<log_level>DEBUG</log_level>

Allowed log levels are:

  • ERROR
  • WARN
  • INFO
  • DEBUG

# Configuration of endpoints

All allowed requests must be configured in the configuration file in the section <endpoints>.

URLs which are not explicitly configured will be handled with a higher-level endpoint. This means that for example a call with the URL /service/amf/abc/cde would be answered by the endpoint with the configuration /service/amf.

<endpoint content_transformer="Download">
  <url>/service/FileAccessDownload</url>
</endpoint>

You can configure the endpoints like this:

type required? description
url XML element yes The URL which is allowed or blocked.
session XML attribute no Attribute from which the session is to be read. For GET and POST requests.
content_transformer XML attribute no Valid values are: download and upload (see below).
deny XML attribute no Blocks explicitly this URL.
destinations XML element no Complex element to configure the handling of AMF requests (see below).
checkAuthorization XML attribute no Default: false. Set to true to activate session check for 4ALLPORTAL 3.7 endpoints. Session cookies and bearer authorization will be checked then.
  • download: Forwards the request immediately, but sets the header content-length. The file size of a download in the browser will only be displayed if more than one chunk is transferred. Otherwise, the header will be deleted automatically.
  • upload: Saves the complete request before it is forwarded. Otherwise, incomplete assets and videos would be created in the DAM.

# Configuration of AMF requests

Example:

<endpoint>
  <url>/service/amf</url>
  <destinations>
    <destination name="ActionRemoteService" type="3"/>
    <destination name="AdministrationRemoteService" type="1">
      <operations type="0">
        <operation>getBaseConfiguration</operation>
        <operation>updateBaseConfiguration</operation>
      </operations>
    </destination>
  </destinations>
</endpoint>

# Destinations

type required? description
name XML attribute yes Name of the AMF endpoint.
type XML attribute no (default: 0) Defines the way how the session is included in the request (see below).
pos XML attribute no (default: 0) Defines in which parameter of the array the session is located.
operations XML element no Allows to define exceptions for certain operations of an AMF endpoint. If not set, the endpoint setting is used (see below).

# Destination types

value description
0 no session
1 session as string
2 session in identVO
3 session in object (derived from SimpleRequestObject)

# Operations

type required? description
type XML attribute no (default: 0) see: destinations
pos XML attribute no (default: 0) see: destinations
access XML attribute no (default: true) False will explicitly block a method.
operation XML elementList yes List of operations to which this setting applies.

# Help

# Show server ciphers

The output depends on the supported SSL protocols and ciphers. For Linux and Mac OSX this may result in different outputs. Use one of these methods to show server ciphers:

# Read out ciphers from HTTPd

#All ciphers
openssl ciphers ${cipherspec} | sed 's/:/\n/g'

#CBC ciphers
 openssl ciphers ${cipherspec} | sed 's/:/\n/g' | grep CBC

# Check certificate chain

To display the certificate chain, execute:

openssl s_client -connect HOSTNAME:443
openssl s_client -verify_return_error -showcerts -connect HOSTNAME:443

The result must be: Verify return code: 0 (ok)

Request missing documentation