From 9c9c877ba7bf0770b4fc196da4d3a09ccf26034c Mon Sep 17 00:00:00 2001 From: Dustyn Blackmore Date: Wed, 16 May 2018 17:34:54 +1000 Subject: [PATCH] Refactor for State Added src/state Allows management of state. immutable and mutable work, but not with get and set. Extends properties to the current state object. Updated code otherwise to include references. --- src/index.js | 69 ++++++++++++++++++++-------------------- src/nfpacket/encoding.js | 6 ++-- src/nfpacket/index.js | 41 ++++++------------------ src/state/immutable.js | 5 +++ src/state/index.js | 28 ++++++++++++++++ src/state/mutable.js | 22 +++++++++++++ 6 files changed, 101 insertions(+), 70 deletions(-) create mode 100644 src/state/immutable.js create mode 100644 src/state/index.js create mode 100644 src/state/mutable.js diff --git a/src/index.js b/src/index.js index 879350c..9aec0e0 100644 --- a/src/index.js +++ b/src/index.js @@ -122,66 +122,66 @@ function handleActions (action, packet) { function handlePacket (packet) { let verdict = { - policy: packet.state.enums.netfilterVerdict.NF_DROP, + policy: packet.enums.netfilterVerdict.NF_DROP, mark: 0 }; // Check we even handle this protocol - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()]) { + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()]) { // Check if the global (blanket) rule applies - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()].global.policy && rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()].global.policy === 'allow') { + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.policy && rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.policy === 'allow') { // Trigger the callback, if it exists.. - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()].global.action) { - handleActions(rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()].global.action, packet); - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()].global.action === 'log') { + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.action) { + handleActions(rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.action, packet); + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.action === 'log') { verdict.mark = 9999; } } // Check if the global setting has any specific ports - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()].global.ports) { + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.ports) { // Check, if there are ports, if the port is allowed. - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()].global.ports[packet.state.nfpacketDecoded.payload.dport]) { + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.dport]) { // Check if the policy is allow - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()].global.ports[packet.state.nfpacketDecoded.payload.dport].policy && rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()].global.ports[packet.state.nfpacketDecoded.payload.dport].policy === 'allow') { + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.dport].policy && rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.dport].policy === 'allow') { // Set to accept packet. - verdict.policy = packet.state.enums.netfilterVerdict.NF_ACCEPT; + verdict.policy = packet.enums.netfilterVerdict.NF_ACCEPT; } // Finally - if the port is allowed, check if there's a callback to trigger. - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()].global.ports[packet.state.nfpacketDecoded.payload.dport].action) { - handleActions(rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()].global.ports[packet.state.nfpacketDecoded.payload.dport].action, packet); - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()].global.ports[packet.state.nfpacketDecoded.payload.dport].action === 'log') { + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.dport].action) { + handleActions(rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.dport].action, packet); + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.dport].action === 'log') { verdict.mark = 9999; } } // Do not further traverse ruleset, or this function ; wasted cycles. - packet.state.nfpacket.setVerdict(verdict.policy, verdict.mark); + packet.nfpacket.setVerdict(verdict.policy, verdict.mark); } // The global default is enabled, yet there is no ports key.. // (Likely) means this is a port-less protocol, or a blanket 'allow' rule is in place. } else { - verdict.policy = packet.state.enums.netfilterVerdict.NF_ACCEPT; - packet.state.nfpacket.setVerdict(verdict.policy, verdict.mark); + verdict.policy = packet.enums.netfilterVerdict.NF_ACCEPT; + packet.nfpacket.setVerdict(verdict.policy, verdict.mark); } // Else, as if globally accepted we don't need to traverse other zones. } // Check if the protocol is zone allowed. - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()][packet.getInterface().zone].policy && rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()][packet.getInterface().zone].policy === 'allow') { + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.interface.zone].policy && rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.interface.zone].policy === 'allow') { // Trigger the protocol zone callback, if it exists. - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()][packet.getInterface().zone].action) { - handleActions(rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()][packet.getInterface().zone].action, packet); - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()][packet.getInterface().zone].action === 'log') { + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.interface.zone].action) { + handleActions(rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.interface.zone].action, packet); + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.interface.zone].action === 'log') { verdict.mark = 9999; } } // Check if the protocol's zone setting has any specific ports - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()][packet.getInterface().zone].ports) { + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.interface.zone].ports) { // Check, if there are ports, if the port is allowed. - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()][packet.getInterface().zone].ports[packet.state.nfpacketDecoded.payload.dport] && rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()][packet.getInterface().zone].ports[packet.state.nfpacketDecoded.payload.dport].policy && rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()][packet.getInterface().zone].ports[packet.state.nfpacketDecoded.payload.dport].policy === 'allow') { - verdict.policy = packet.state.enums.netfilterVerdict.NF_ACCEPT; + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.interface.zone].ports[packet.nfpacketDecoded.payload.dport] && rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.interface.zone].ports[packet.nfpacketDecoded.payload.dport].policy && rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.interface.zone].ports[packet.nfpacketDecoded.payload.dport].policy === 'allow') { + verdict.policy = packet.enums.netfilterVerdict.NF_ACCEPT; // Finally - if the port is allowed, check if there's a callback to trigger. - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()][packet.getInterface().zone].ports[packet.state.nfpacketDecoded.payload.dport].action) { - handleActions(rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()][packet.getInterface().zone].ports[packet.state.nfpacketDecoded.payload.dport].action, packet); - if (rules[packet.getDirection()][packet.state.nfpacketDecoded.protocol.toString()][packet.getInterface().zone].ports[packet.state.nfpacketDecoded.payload.dport].action === 'log') { + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.interface.zone].ports[packet.nfpacketDecoded.payload.dport].action) { + handleActions(rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.interface.zone].ports[packet.nfpacketDecoded.payload.dport].action, packet); + if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.interface.zone].ports[packet.nfpacketDecoded.payload.dport].action === 'log') { verdict.mark = 9999; } } @@ -189,13 +189,12 @@ function handlePacket (packet) { // The global default is enabled, yet there are no ports.. which likely // Means this is a port-less protocol. } else { - verdict.policy = packet.state.enums.netfilterVerdict.NF_ACCEPT; + verdict.policy = packet.enums.netfilterVerdict.NF_ACCEPT; } } } - console.log(verdict.policy); - packet.state.nfpacket.setVerdict(verdict.policy, verdict.mark); + packet.nfpacket.setVerdict(verdict.policy, verdict.mark); } function updateOutput () { @@ -207,9 +206,9 @@ function bindQueueHandlers () { interfaces.forEach(interface => { interface.queueIn = nfq.createQueueHandler(parseInt(interface.number), buffer, (nfpacket) => { let thisPacket = netFilterPacket(nfpacket); - thisPacket.setDirection('incoming'); - thisPacket.setInterface(interface); - + thisPacket.direction = 'incoming'; + thisPacket.interface = interface; + thisPacket.encoding.decode(); handlePacket(thisPacket); @@ -227,9 +226,9 @@ function bindQueueHandlers () { interface.queueOut = nfq.createQueueHandler(parseInt('100' + interface.number), buffer, (nfpacket) => { let thisPacket = netFilterPacket(nfpacket); - thisPacket.setDirection('outgoing'); - thisPacket.setInterface(interface); - + thisPacket.direction = 'outgoing'; + thisPacket.interface = interface; + thisPacket.encoding.decode(); handlePacket(thisPacket); diff --git a/src/nfpacket/encoding.js b/src/nfpacket/encoding.js index 9ba9633..e6eb6e7 100644 --- a/src/nfpacket/encoding.js +++ b/src/nfpacket/encoding.js @@ -1,10 +1,10 @@ const encoding = (dependencies) => (state) => ({ decode: () => { let IPv4 = dependencies || null; - - state.nfpacketDecoded = IPv4 + let nfpacketDecoded = IPv4 ? new IPv4().decode(state.nfpacket.payload, 0) - : false; + : false + state.nfpacketDecoded = nfpacketDecoded; } }) diff --git a/src/nfpacket/index.js b/src/nfpacket/index.js index 6a4db8d..b6c20fd 100644 --- a/src/nfpacket/index.js +++ b/src/nfpacket/index.js @@ -1,45 +1,22 @@ const actions = require('./actions'); const encoding = require('./encoding'); const enums = require('./enums.js'); - -const setDirection = (state) => (direction) => { - if (direction === 'incoming' || direction === 'outgoing') { - state.direction = direction; - } else { - state.direction = undefined; - } -} - -const getDirection = (state) => () => { - return state.direction; -} - -const setInterface = (state) => (interface) => { - state.interface = interface; -} - -const getInterface = (state) => () => { - return state.interface; -} +const statable = require('./../state'); module.exports = (dependencies) => (nfpacket) => { - let state = { - nfpacket: nfpacket, - enums: enums, + let state = statable('mutable')({ direction: undefined, - interface: undefined - } + enums: enums, + interface: undefined, + nfpacket: nfpacket, + }); + if (Object.keys(dependencies).includes('nfq') && Object.keys(dependencies).includes('pcapIPv4')) { return Object.assign( - {}, + state, { actions: actions(dependencies)(state), - encoding: encoding(dependencies.pcapIPv4)(state), - getDirection: getDirection(state), - getInterface: getInterface(state), - setDirection: setDirection(state), - setInterface: setInterface(state), - state + encoding: encoding(dependencies.pcapIPv4)(state) } ); } diff --git a/src/state/immutable.js b/src/state/immutable.js new file mode 100644 index 0000000..2ccdf88 --- /dev/null +++ b/src/state/immutable.js @@ -0,0 +1,5 @@ +module.exports = (state) => ({ + get: (property) => { + return state.property || undefined; + } +}); diff --git a/src/state/index.js b/src/state/index.js new file mode 100644 index 0000000..407a6e1 --- /dev/null +++ b/src/state/index.js @@ -0,0 +1,28 @@ +const immutable = require('./immutable'); +const mutable = require('./mutable'); + +module.exports = (type) => (initialState) => { + let state = {}; + + if (typeof initialState !== 'undefined') { + state = initialState; + } + + if (typeof type === 'string' && (type === 'mutable' || type === 'immutable')) { + if (type === 'immutable') { + return Object.freeze(Object.assign( + state, + immutable(state), + )); + } + + if (type === 'mutable') { + return Object.assign( + state, + mutable(state), + ) + } + } + + return state; +} diff --git a/src/state/mutable.js b/src/state/mutable.js new file mode 100644 index 0000000..f0603c2 --- /dev/null +++ b/src/state/mutable.js @@ -0,0 +1,22 @@ +const checkSetObject = (setObject) => { + return typeof Object.keys(setObject)[0] !== undefined; +} + +module.exports = (state) => ({ + get: (property) => { + return state[property] || undefined; + }, + set: (setObject) => { + if (checkSetObject(setObject)) { + let currentState = Object.assign({}, state); + + let targetProperty = Object.keys(setObject)[0]; + let targetValue = setObject[targetProperty]; + + console.log('Attempting to set %s, with %s.', targetProperty, targetValue); + let newState = Object.assign({ [targetProperty]: targetValue }, currentState); + + state = newState; + } + } +});