Skip to content

Latest commit

 

History

History
114 lines (79 loc) · 2.98 KB

Split-Horizon.md

File metadata and controls

114 lines (79 loc) · 2.98 KB

Split-Horizon Topology testing

A simple reproduction for split-horizon testing. We simulate a port forwarding topology use case using port address translation (PAT).

Installation

Add PAT rules (taken from https://salferrarello.com/mac-pfctl-port-forwarding/), and enable kernel IP forwarding

echo "
rdr on en0 proto tcp to any port 37017 -> 127.0.0.1 port 27017
rdr on en0 proto tcp to any port 37018 -> 127.0.0.1 port 27018
rdr on en0 proto tcp to any port 37019 -> 127.0.0.1 port 27019
" | sudo pfctl -ef -
sudo sysctl -w net.inet.ip.forwarding=1
sudo sysctl -w net.inet6.ip6.forwarding=1

OSX: Disable the firewall in system preferences

Verification

Display your current port forwarding rules:

sudo pfctl -s nat

Scan for listening ports

nmap -sT -p 27017-27019,37017-37019 localhost external

Validate the SNI header by inspecting the returned SSL subject/SAN attributes. Using the TLS Server tests as a basis, we can fomulate this command:

openssl s_client -connect external:27017 < /dev/null | openssl x509 -noout -text | grep "subject=\|Subject:\|X509v3\ Subject\ Alternative\ Name:\|DNS:"

Uninstallation

Remove all rules and forwarding

sudo pfctl -F all -f /etc/pf.conf
sudo sysctl -w net.inet.ip.forwarding=0
sudo sysctl -w net.inet6.ip6.forwarding=0

Build a replica set

Start with a standard deployment with TLS enabled (required for split-horizon support), here using the mongodb.pk8 certificate (see sample certificates)

mlaunch init --replicaset --tlsMode preferTLS --tlsCAFile mongodb.pk8 --tlsPEMKeyFile mongodb.pk8 --tlsAllowConnectionsWithoutCertificates

Ensure correct hostname resolution

Modify /etc/hosts if required, using "external" at the external PAT bound hostname

Update the replica set topology

As reported by db.hello()

Connect without TLS:

mongosh "mongodb://localhost:27017/?replicaSet=replset&readPreference=primary"

Add the split-horizon topology definitions

let horizons = [
   { "external": "external:37017" },
   { "external": "external:37018" },
   { "external": "external:37019" }
];
rs.reconfig({
   ...rs.conf(),
   "members": rs.conf().members.map(member => ({
      ...member,
      "horizons": horizons[member._id]
   }))
});

Testing

Connect to the native port:

mongosh "mongodb://localhost:27017/?replicaSet=replset" --tlsCAFile mongodb.pk8 --tls --eval 'db.hello().hosts'

The SDAM topology should appear as:

["localhost:27017", "localhost:27018", "localhost:27019"]

Connect to the translated port:

mongosh "mongodb://external:37017,external:37018,external:37019/?replicaSet=replset" --tlsCAFile mongodb.pk8 --tls --eval 'db.hello().hosts'

The SDAM topology should appear as:

["external:37017", "external:37018", "external:37019"]