Linux-UNIX: Neo4J auditing configuration

Use a double proxy together with either K-TAP or PCAP to capture encrypted Neo4J traffic.

About this task

This procedure requires two proxies of either NGINX or HAProxy type. Both must both be located on the database.

The first proxy instance terminates the SSL and adds a proxy protocol to ports 7687 and 7473. The second proxy instance listens to the intermediate ports (17687 and 17473) and removes the proxy protocol. K-TAP or PCAP intercepts the traffic between the two proxy instances. Outgoing decrypted traffic from Proxy2 is sent to unecrypted Neo4j database ports (27687, 7474).

Procedure

  1. Configure the database.
    Neo4J advertises the ports it uses. The ports need to be changed to avoid conflicting with the proxy ports: Neo4J needs to have its port configuration changed and the proxy entry point ports need to be configured for advertising (requires version 3.5.0 or newer). In the neo4j configuration file: /home/neo4j/neo4j/conf/neo4j.conf, add/edit these lines. In this example the DB server is rh7u3x64t-ktap.databaseserver.
    dbms.connector.bolt.listen_address=127.0.0.1:27687
    dbms.connector.bolt.advertised_address=rh7u3x64t-ktap:7687
    dbms.connector.http.listen_address=127.0.0.1:7474
    dbms.connector.https.listen_address=127.0.0.1:27473
    dbms.connector.https.advertised_address=rh7u3x64t-ktap:7473
  2. Configure HAProxy. (Not required if you are using NGINX.)
    In the HAProxy configuration file /etc/haproxy/haproxy.cfg:
    • Enable the Proxy Protocol in Proxy1(HAProxy1) by adding the send-proxy keyword to the backend.
    • Strip the Proxy protocol in Proxy2(HAProxy2) by adding accept-proxy to the frontend.
    frontend  main
        bind *:7687 ssl crt /home/ne04j/neo4j/certificates/neo4j.pem
        mode tcp
        default_backend send_proxy_protocol
    
    backend send_proxy_protocol
        balance roundrobin
        server  app1 127.0.0.1:17687 send-proxy
    
    frontend  strip_proxy_protocol
        bind 127.0.0.1:17687 accept-proxy
        mode tcp
        default_backend neo4j
    
    backend neo4j
        balance roundrobin
        server  app1 127.0.0.1:27687
  3. Configure NGINX. (Not required if you are using HAProxy.)

    For a TCP stream, the PROXY protocol can be enabled for connections between NGINX and an upstream server. To enable the PROXY protocol in Proxy1(Nginx1), include the proxy_protocol directive in a server block at the stream{} level in /etc/nginx/nginx.conf. NGINX terminates HTTPS traffic (the ssl_certificate and ssl_certificate_key directives) and proxies the decrypted data to a backend server. In Proxy2(Nginx2), add listen with proxy_protocol to receive the client’s real IP forwarded with Proxy Protocol.

    1. Make sure that your NGINX installation includes the HTTP and Stream Real IP modules:
      • nginx -V 2>&1 | grep -- 'http_realip_module'
      • nginx -V 2>&1 | grep -- 'stream_realip_module'
    2. In the file /etc/nginx/nginx.conf, add:
      stream {
              upstream neo4jweb {
                      server localhost:7474;
              }
              upstream neo4jbolt {
                      server localhost:27687;
              }
      
              server {
                      listen 7473        ssl;
                      proxy_pass          localhost:17473;
                      proxy_protocol      on;
                      ssl_certificate     /home/ne04j/neo4j/certificates/neo4j.cert;
                      ssl_certificate_key /home/ne04j/neo4j/certificates/neo4j.key;
              }
              server {
                      listen 7687        ssl;
                      proxy_pass          localhost:17687;
                      proxy_protocol      on;
                      ssl_certificate     /home/ne04j/neo4j/certificates/neo4j.cert;
                      ssl_certificate_key /home/ne04j/neo4j/certificates/neo4j.key;
              }
              server {
                      listen 17473        proxy_protocol;
                      proxy_pass          neo4jweb;
              }
              server {
                      listen 17687        proxy_protocol;
                      proxy_pass          neo4jbolt;
              }
      }
  4. Configure the network.
    Verify that all traffic from the client is sent to Proxy1. Any traffic that does not go from Proxy2 to DB is dropped. This requires IPTABLE setup. Use this script neo4j_firewall.sh to set up the IPTABLES:
    #!/bin/sh
    
    # Remove any existing jumps to our custom chains
    iptables -D INPUT  -j chain-neo4j-incoming
    iptables -D OUTPUT -j chain-neo4j-outgoing
    
    # Clean any existing custom chains
    iptables -F chain-neo4j-incoming
    iptables -F chain-neo4j-outgoing
    iptables -X chain-neo4j-incoming
    iptables -X chain-neo4j-outgoing
    iptables -N chain-neo4j-incoming
    iptables -N chain-neo4j-outgoing
    
    # Define external(proxy1), proxy2, ssl and no ssl ports 
    no_ssl_port_prefix=2
    proxy2_port_prefix=1
    port_list=0
    
    # Pass in all arguments, please see bottom usage.
    for i in "$@" ; do
      # set the port prefix
      if echo $i | grep '^-' > /dev/null; then
        if echo $i | grep '^-port_list$' > /dev/null; then
          port_list=999
        fi
      elif [ "X${port_list}" = "X999" ]; then
         external_port=${i}
         proxy2_port=${proxy2_port_prefix}${i}
         no_ssl_port=${no_ssl_port_prefix}${i}
         if [  “${external_port}” = “7473” ]; then
            no_ssl_port=7474
         fi
        ####################################
        # INCOMING RULES
    
        # Allow loopback access to intermediate ports so that proxy1 can
        # route traffic to proxy2
        iptables -A chain-neo4j-incoming -i lo -p tcp --dport ${proxy2_port} -j ACCEPT
    
        # Disallow external access to proxy2
        iptables -A chain-neo4j-incoming -p tcp --dport ${proxy2_port} -j REJECT
    
        # Allow loopback access to unencrypted ports so that proxy2 can
        # route traffic to DB
        iptables -A chain-neo4j-incoming -i lo -p tcp --dport ${no_ssl_port} -j ACCEPT
    
        # Disallow direct access to unencrypted ports
        iptables -A chain-neo4j-incoming -p tcp --dport ${no_ssl_port} -j REJECT
    
        # Allow access to proxy1
        iptables -A chain-neo4j-incoming -p tcp --dport ${external_port} -j ACCEPT
    
        ####################################
        # OUTGOING RULES
    
        # Allow loopback access to unencrypted ports to allow routing from proxy2 to
        # DB (proxy2 runs under neo4j UID)
        iptables -A chain-neo4j-outgoing -o lo -p tcp --dport ${no_ssl_port} -m owner --uid neo4j -j ACCEPT
    
        # Allow loopback access to intermediate ports to allow routing from proxy1 to
        # proxy2 (proxy1 runs under neo4j UID)
        iptables -A chain-neo4j-outgoing -o lo -p tcp --dport ${proxy2_port} -m owner --uid neo4j -j ACCEPT
    
        # Disallow loopback access to unencrypted ports to prevent local clients from
        # skipping interception
        iptables -A chain-neo4j-outgoing -o lo -p tcp --dport ${no_ssl_port} -j REJECT
      fi
    done
    
    if [ "${port_list}" = "0" ]; then
        echo “usage: /root/set_firewall.sh -port_list [external port list]”
        echo “for example /root/set_firewall.sh -port_list 7473 7687”
    fi
    
    
    # Firewall chains need to return at the end
    iptables -A chain-neo4j-incoming -j RETURN
    iptables -A chain-neo4j-outgoing -j RETURN
    
    # Hook the main rules up to the chains
    iptables -A INPUT  -j chain-neo4j-incoming
    iptables -A OUTPUT -j chain-neo4j-outgoing
    
  5. Configure the S-TAP®.
    When configuring the proxy instances, the first instance terminates the encryption and adds the proxy-protocol for Guardium to collect the traffic and be able to attribute the correct analyzed client IP. The second instance removes the proxy-protocol, to not break the connection to the database. Configure the inspection engine to collect the traffic between the two proxy instances. For example, if you are using the example configurations above, then the ports to collect for Neo4j are 17473, 17687.
    • If you are using K-TAP, modify the guard_tap.ini file:
      • IE parameters
        [DB_0]
        db_type=NEO4J
        port_range_end=17473
        port_range_start=17473
        real_db_port=17473
        networks=127.0.0.1/255.255.255.255,9.70.165.199/255.255.255.255
        
        [DB_1]
        db_type=NEO4J
        port_range_end=17687
        port_range_start=17687
        real_db_port=17687
        networks=127.0.0.1/255.255.255.255,9.70.165.199/255.255.255.255
    • If you are using PCAP, modify the guard_tap.ini file:
      • TAP properties
        devices=ens32,lo
        ktap_installed=0
      • IE parameters
        [DB_0]
        db_type=NEO4J
        port_range_end=17473
        port_range_start=17473
        real_db_port=17473
        
        [DB_1]
        db_type=NEO4J
        port_range_end=17687
        port_range_start=17687
        real_db_port=17687