Skip to content

Commit

Permalink
Feat/add tls support (#9)
Browse files Browse the repository at this point in the history
* feat: add TLS details extractor

* fix: ignore .DS_Store

* test: check that TLS connections can be verified

* doc: add info about TLS extraction

* chore: update dependencies

* fix: resolve new lint rules issue

* test: move tests and fixture in test folder
  • Loading branch information
getlarge authored Jun 28, 2021
1 parent e5b5e34 commit ee47e7e
Show file tree
Hide file tree
Showing 13 changed files with 258 additions and 89 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,5 @@ dist
.tern-port

package-lock.json

.DS_Store
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Protocol decoder for Aedes MQTT Broker
The purpose of this module is to be used inside [aedes-server-factory](https://github.com/moscajs/aedes-server-factory) `bindConnection` function, which is called when the server receives a connection from client (before CONNECT packet). The client object state is in default and its connected state is false.
The function extract socket details and if `aedes-server-factory` `trustProxy` option is set to true, it will first parse http headers (x-real-ip | x-forwarded-for) and/or proxy protocol (v1 and v2), then passing the informations to `aedes` that will assign them to `client.connDetails`.

Additionally, if the current socket is a [TLS](https://nodejs.org/api/tls.html#tls_class_tls_tlssocket) socket, the module will extract the authorization status and the full certificate chain.

The function `protocolDecoder` and `extractSocketDetails` returns [ConnectionDetails](./types/index.d.ts), if the object contains `data` property, it will be parsed as an [mqtt-packet](https://github.com/mqttjs/mqtt-packet).

## Install
Expand Down
40 changes: 20 additions & 20 deletions example.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
'use strict'

var aedes = require('aedes')
var mqttPacket = require('mqtt-packet')
var net = require('net')
var proxyProtocol = require('proxy-protocol-js')
var { createServer } = require('aedes-server-factory')
var { extractSocketDetails, protocolDecoder } = require('./index')
const aedes = require('aedes')
const mqttPacket = require('mqtt-packet')
const net = require('net')
const proxyProtocol = require('proxy-protocol-js')
const { createServer } = require('aedes-server-factory')
const { extractSocketDetails, protocolDecoder } = require('./index')

var brokerPort = 4883
const brokerPort = 4883

// from https://stackoverflow.com/questions/57077161/how-do-i-convert-hex-buffer-to-ipv6-in-javascript
function parseIpV6 (ip) {
Expand All @@ -19,19 +19,19 @@ function parseIpV6 (ip) {
}

function sendProxyPacket (version = 1, ipFamily = 4) {
var packet = {
const packet = {
cmd: 'connect',
protocolId: 'MQTT',
protocolVersion: 4,
clean: true,
clientId: `my-client-${version}`,
keepalive: 0
}
var hostIpV4 = '0.0.0.0'
var clientIpV4 = '192.168.1.128'
var hostIpV6 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
var clientIpV6 = [0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 192, 168, 1, 128]
var protocol
const hostIpV4 = '0.0.0.0'
const clientIpV4 = '192.168.1.128'
const hostIpV6 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
const clientIpV6 = [0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 192, 168, 1, 128]
let protocol
if (version === 1) {
if (ipFamily === 4) {
protocol = new proxyProtocol.V1BinaryProxyProtocol(
Expand Down Expand Up @@ -76,16 +76,16 @@ function sendProxyPacket (version = 1, ipFamily = 4) {
}
}

var parsedProto = version === 1
const parsedProto = version === 1
? proxyProtocol.V1BinaryProxyProtocol.parse(protocol)
: proxyProtocol.V2ProxyProtocol.parse(protocol)
// console.log(parsedProto)

var dstPort = version === 1
const dstPort = version === 1
? parsedProto.destination.port
: parsedProto.proxyAddress.destinationPort

var dstHost
let dstHost
if (version === 1) {
if (ipFamily === 4) {
dstHost = parsedProto.destination.ipAddress
Expand All @@ -103,23 +103,23 @@ function sendProxyPacket (version = 1, ipFamily = 4) {
}

console.log('Connection to :', dstHost, dstPort)
var mqttConn = net.createConnection(
const mqttConn = net.createConnection(
{
port: dstPort,
host: dstHost,
timeout: 150
}
)

var data = protocol
const data = protocol

mqttConn.on('timeout', function () {
mqttConn.end(data)
})
}

function startAedes () {
var broker = aedes({
const broker = aedes({
preConnect: function (client, packet, done) {
console.log('Aedes preConnect check client ip:', client.connDetails)
if (client.connDetails && client.connDetails.ipAddress) {
Expand All @@ -130,7 +130,7 @@ function startAedes () {
}
})

var server = createServer(broker, { trustProxy: true, extractSocketDetails, protocolDecoder })
const server = createServer(broker, { trustProxy: true, extractSocketDetails, protocolDecoder })

server.listen(brokerPort, function () {
console.log('Aedes listening on :', server.address())
Expand Down
13 changes: 12 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ function extractProxyDetails (buffer, proto = {}) {
return proto
}

function extractSocketTLSDetails (socket, proto = {}) {
socket = socket._socket || socket
if (socket.getPeerCertificate && typeof socket.getPeerCertificate === 'function') {
proto.certAuthorized = socket.authorized
proto.cert = socket.getPeerCertificate(true)
}
return proto
}

function extractSocketDetails (socket, proto = {}) {
if (socket._socket && socket._socket.address) {
proto.isWebsocket = true
Expand All @@ -107,6 +116,7 @@ function extractSocketDetails (socket, proto = {}) {
proto.serverIpAddress = socket.address().address
proto.ipFamily = getProtoIpFamily(socket.remoteFamily)
}
extractSocketTLSDetails(socket, proto)
return proto
}

Expand All @@ -118,9 +128,10 @@ function protocolDecoder (conn, buffer, req) {
proto.isWebsocket = false
extractHttpDetails(req, socket, proto)
extractProxyDetails(buffer, proto)

if (!proto.ipAddress) {
extractSocketDetails(socket, proto)
} else {
extractSocketTLSDetails(socket, proto)
}

return proto
Expand Down
30 changes: 15 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
"lint": "npm run lint:standard && npm run lint:typescript",
"lint:standard": "standard --verbose | snazzy",
"lint:typescript": "standard --parser @typescript-eslint/parser --plugin @typescript-eslint/eslint-plugin types/**/*.d.ts",
"unit": "tape test.js | faucet",
"unit": "tape test/test.js | faucet",
"test": "npm run lint && npm run unit",
"coverage": "nyc --reporter=lcov tape test.js",
"coverage": "nyc --reporter=lcov tape test/test.js",
"test:ci": "npm run lint && npm run coverage",
"license-checker": "license-checker --production --onlyAllow='MIT;ISC;BSD-3-Clause;BSD-2-Clause'",
"release": "read -p 'GITHUB_TOKEN: ' GITHUB_TOKEN && export GITHUB_TOKEN=$GITHUB_TOKEN && release-it"
Expand Down Expand Up @@ -65,24 +65,24 @@
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.1",
"@typescript-eslint/eslint-plugin": "^2.30.0",
"@typescript-eslint/parser": "^2.30.0",
"aedes": "^0.44.0",
"aedes-server-factory": "git+https://git@github.com/getlarge/aedes-server-factory.git#create-server-factory",
"@typescript-eslint/eslint-plugin": "^4.28.0",
"@typescript-eslint/parser": "^4.28.0",
"aedes": "^0.46.0",
"aedes-server-factory": "0.1.3",
"faucet": "0.0.1",
"license-checker": "^25.0.1",
"mqtt": "^4.0.0",
"mqtt-packet": "^6.5.0",
"nyc": "^15.0.0",
"mqtt": "^4.2.8",
"mqtt-packet": "^7.0.0",
"nyc": "^15.1.0",
"pre-commit": "^1.2.2",
"release-it": "^14.2.2",
"snazzy": "^8.0.0",
"standard": "^14.3.3",
"tape": "^4.13.0",
"typescript": "^4.0.2"
"release-it": "^14.10.0",
"snazzy": "^9.0.0",
"standard": "^16.0.3",
"tape": "^5.2.0",
"typescript": "^4.3.4"
},
"dependencies": {
"forwarded": "^0.1.2",
"forwarded": "^0.2.0",
"proxy-protocol-js": "^4.0.5"
}
}
11 changes: 11 additions & 0 deletions test/fixtures/client-1-crt.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBjzCCATQCFCMLUhJyzJp8YaGxPb9UB7sIzbAdMAoGCCqGSM49BAMCMEYxCzAJ
BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMQ4wDAYDVQQKDAVNb3NjYTES
MBAGA1UEAwwJY2Etc2VydmVyMB4XDTIxMDYyNzEzNTc1MloXDTQ4MTExMTEzNTc1
MlowTTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxDjAMBgNVBAoM
BU1vc2NhMRkwFwYDVQQDDBBjbGllbnQubG9jYWxob3N0MFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAEGQV5HV7KIxLSCxnUusWmW5INyalnBr/drtQDPDgjzgkcyd1n
23yhKknsAy5XA/cLdtRhBH0NtxI17vH/KErqJDAKBggqhkjOPQQDAgNJADBGAiEA
lsp7WYh73+rmQ0PV8PQDYpbBOFh9Mt6uBFUeeZh1CiYCIQD6M9HNC8wh8xevokbD
YeSd/IR6vGSN1yy9fp1HFU6yxA==
-----END CERTIFICATE-----
8 changes: 8 additions & 0 deletions test/fixtures/client-1.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEINLPiNgjbRWJEucUxnBQXJi6YPjf3tW0GAXUoQaAiu5ToAoGCCqGSM49
AwEHoUQDQgAEGQV5HV7KIxLSCxnUusWmW5INyalnBr/drtQDPDgjzgkcyd1n23yh
KknsAy5XA/cLdtRhBH0NtxI17vH/KErqJA==
-----END EC PRIVATE KEY-----
13 changes: 13 additions & 0 deletions test/fixtures/ec-cacert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB4TCCAYegAwIBAgIULwEbjhdwdLLdyKZ2WoMTB5hCVoIwCgYIKoZIzj0EAwIw
RjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxDjAMBgNVBAoMBU1v
c2NhMRIwEAYDVQQDDAljYS1zZXJ2ZXIwHhcNMjEwNjI3MTM1MTA4WhcNMzEwNjI1
MTM1MTA4WjBGMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEOMAwG
A1UECgwFTW9zY2ExEjAQBgNVBAMMCWNhLXNlcnZlcjBZMBMGByqGSM49AgEGCCqG
SM49AwEHA0IABBWVkbZSDFOjT6WOZyteZi+vuBZS7z9G1ih+8eNwCGthSOz+pihv
5nlNGoPAVMwTHckF++za3f6BoMhxBPhv1mejUzBRMB0GA1UdDgQWBBS9VE5Wme+J
yMRK2/K8iqykLHpo9DAfBgNVHSMEGDAWgBS9VE5Wme+JyMRK2/K8iqykLHpo9DAP
BgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIQCAATupf1g8xy80dPPf
U1xcyIriNijscNg92qP/w2VCPgIgTFNhrePMXAw8cRuKE2CtZsErMhC1PrYFdfzi
YucJJY0=
-----END CERTIFICATE-----
8 changes: 8 additions & 0 deletions test/fixtures/ec-cakey.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIA6EN3jpiyZeUl2h95QIxsnWOylF1zS7IJxtn6LHp3P0oAoGCCqGSM49
AwEHoUQDQgAEFZWRtlIMU6NPpY5nK15mL6+4FlLvP0bWKH7x43AIa2FI7P6mKG/m
eU0ag8BUzBMdyQX77Nrd/oGgyHEE+G/WZw==
-----END EC PRIVATE KEY-----
11 changes: 11 additions & 0 deletions test/fixtures/server-crt.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBiDCCAS0CFCMLUhJyzJp8YaGxPb9UB7sIzbAcMAoGCCqGSM49BAMCMEYxCzAJ
BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMQ4wDAYDVQQKDAVNb3NjYTES
MBAGA1UEAwwJY2Etc2VydmVyMB4XDTIxMDYyNzEzNTUxMloXDTQ4MTExMTEzNTUx
MlowRjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxDjAMBgNVBAoM
BU1vc2NhMRIwEAYDVQQDDAlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMB
BwNCAARqmDuclP12svM/CtIfUA1QEZdsDbx7Y7oNvPeWmXE+6qIqHHu6MrM27Tn8
NM1VFC7UQkGDIUVPb2Byn68dkh4zMAoGCCqGSM49BAMCA0kAMEYCIQDEgYqstnfz
+CFLZ2GLO4j4qf1zBxp1cHgL3OwsetcpYAIhAIyIJ3g9fRORWTGUwq9auoIZB2ms
oegGJadAvTpD4Fuk
-----END CERTIFICATE-----
8 changes: 8 additions & 0 deletions test/fixtures/server.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIHUcEePCyvrrxbTx9NA2OzSqG4OqqRs5DzehdVbQumL6oAoGCCqGSM49
AwEHoUQDQgAEapg7nJT9drLzPwrSH1ANUBGXbA28e2O6Dbz3lplxPuqiKhx7ujKz
Nu05/DTNVRQu1EJBgyFFT29gcp+vHZIeMw==
-----END EC PRIVATE KEY-----
Loading

0 comments on commit ee47e7e

Please sign in to comment.