UNPKG

mecano

Version:

Common functions for system deployment.

270 lines (263 loc) 10.4 kB
misc = require './index' string = require './string' jsesc = require 'jsesc' module.exports = iptables = # add_properties: ['target', 'protocol', 'dport', 'in-interface', 'out-interface', 'source', 'destination'] add_properties: [ '--protocol', '--source', '---destination', '--jump', '--goto' '--in-interface', '--out-interface', '--fragment' 'tcp|--source-port', 'tcp|--sport', 'tcp|--destination-port', 'tcp|--dport', 'tcp|--tcp-flags', 'tcp|--syn', 'tcp|--tcp-option' 'udp|--source-port', 'udp|--sport', 'udp|--destination-port', 'udp|--dport' ] # # modify_properties: ['state', 'comment'] modify_properties: [ '--set-counters', '--log-level', '--log-prefix', '--log-tcp-sequence', '--log-tcp-options', # LOG '--log-ip-options', '--log-uid', # LOG 'state|--state', 'comment|--comment' 'limit|--limit'] commands_arguments: # Used to compute rulenum '-A': ['chain'] '-D': ['chain'] '-I': ['chain'] '-R': ['chain'] '-N': ['chain'] '-X': ['chain'] '-P': ['chain', 'target'] '-L': true, '-S': true, '-F': true, '-Z': true, '-E': true commands_inverted: '--append': '-A' '--delete': '-D' '--insert': '-I' '--replace': '-R' '--new-chain': '-N' '--delete-chain': '-X' '--policy': '-P' '--list': '-L' '--list-rules': '-S' '--flush': '-F' '--zero': '-Z' '--rename-chain': '-E' # parameters: ['-p', '-s', '-d', '-j', '-g', '-i', '-o', '-f', '-c'] # , '--log-prefix' # parameters_inverted: # '--protocol': '-p', '--source': '-s', '--destination': '-d', '--jump': '-j' # '--goto': '-g', '--in-interface': '-i', '--out-interface': '-o', # '--fragment': '-f', '--set-counters': '-c' parameters: ['--protocol', '--source', '--destination', '--jump', '--goto', '--in-interface', '--out-interface', '--fragment', '--set-counters', '--log-level', '--log-prefix', '--log-tcp-sequence', '--log-tcp-options', # LOG '--log-ip-options', '--log-uid' # LOG ] parameters_inverted: '-p': '--protocol', '-s': '--source', '-d': '--destination', '-j': '--jump' '-g': '--goto', '-i': '--in-interface', '-o': '--out-interface', '-f': '--fragment', '-c': '--set-counters' protocols: tcp: ['--source-port', '--sport', '--destination-port', '--dport', '--tcp-flags', '--syn', '--tcp-option'] udp: ['--source-port', '--sport', '--destination-port', '--dport'] udplite: [] icmp: [] esp: [] ah: [] sctp: [] all: [] modules: state: ['--state'] comment: ['--comment'] limit: ['--limit'] cmd_args: (cmd, rule) -> for k, v of rule continue if ['chain', 'rulenum', 'command'].indexOf(k) isnt -1 continue unless v? if match = /^([\w]+)\|([-\w]+)$/.exec k module = match[1] arg = match[2] cmd += " -m #{module}" cmd += " #{arg} #{v}" else cmd += " #{k} #{v}" cmd cmd_replace: (rule) -> rule.rulenum ?= 1 iptables.cmd_args "iptables -R #{rule.chain} #{rule.rulenum}", rule cmd_insert: (rule) -> rule.rulenum ?= 1 iptables.cmd_args "iptables -I #{rule.chain} #{rule.rulenum}", rule cmd_append: (rule) -> rule.rulenum ?= 1 iptables.cmd_args "iptables -A #{rule.chain}", rule cmd: (oldrules, newrules) -> cmds = [] new_chains = [] old_chains = oldrules .map (oldrule) -> oldrule.chain .filter (chain, i, chains) -> ['INPUT', 'FORWARD', 'OUTPUT'].indexOf(chain) < 0 and chains.indexOf(chain) >= i # Create new chains for newrule in newrules if ['INPUT', 'FORWARD', 'OUTPUT'].indexOf(newrule.chain) < 0 and new_chains.indexOf(newrule.chain) < 0 and old_chains.indexOf(newrule.chain) < 0 new_chains.push newrule.chain cmds.push "iptables -N #{newrule.chain}" for newrule in newrules # break if newrule.rulenum? #or newrule.command is '-A' if newrule.after and not newrule.rulenum rulenum = 0 for oldrule, i in oldrules continue unless oldrule.command is '-A' and oldrule.chain is newrule.chain rulenum++ if misc.object.equals newrule.after, oldrule, Object.keys newrule.after # newrule.rulenum = rulenum + 1 newrule.rulenum = oldrule.rulenum + 1 # break delete newrule.after if newrule.before and not newrule.rulenum rulenum = 0 for oldrule, i in oldrules continue unless oldrule.command is '-A' and oldrule.chain is newrule.chain rulenum++ if misc.object.equals newrule.before, oldrule, Object.keys newrule.before # newrule.rulenum = rulenum newrule.rulenum = oldrule.rulenum break delete newrule.before create = true # Get add properties present in new rule add_properties = misc.array.intersect iptables.add_properties, Object.keys newrule for oldrule in oldrules continue if oldrule.chain isnt newrule.chain # Add properties are the same if misc.object.equals newrule, oldrule, add_properties create = false # Check if we need to update if not misc.object.equals newrule, oldrule, iptables.modify_properties # Remove the command baserule = misc.merge {}, oldrule for k, v of baserule baserule[k] = undefined if iptables.commands_arguments[k] baserule.command = undefined newrule.rulenum = undefined cmds.push iptables.cmd_replace misc.merge baserule, newrule # Add properties are different if create cmds.push if newrule.command is '-A' then iptables.cmd_append newrule else iptables.cmd_insert newrule cmds normalize: (rules, position = true) -> oldrules = if Array.isArray rules then rules else [rules] newrules = [] for rule in oldrules rule = misc.merge {}, rule newrule = {} # Search for commands and parameters for k, v of rule nk = null # Normalize value as string v = rule[k] = "#{v}" if typeof v is 'number' # Normalize key as shortname (eg "-k") if k is 'chain' or k is 'rulenum' or k is 'command' # Final name, mark key as done nk = k else if k[0..1] is '--' and iptables.parameters.indexOf(k) >= 0 # nk = iptables.parameters_inverted[k] nk = k else if k[0] isnt '-' and iptables.parameters.indexOf("--#{k}") >= 0 # nk = iptables.parameters_inverted["--#{k}"] nk = "--#{k}" # else if iptables.parameters.indexOf(k) isnt -1 else if iptables.parameters_inverted[k] nk = iptables.parameters_inverted[k] # nk = k # Key has changed, replace it if nk newrule[nk] = v rule[k] = null # Add prototol specific options if protocol = newrule['--protocol'] for k in iptables.protocols[protocol] if rule[k] newrule["#{protocol}|#{k}"] = rule[k] rule[k] = null else if rule[k[2..]] newrule["#{protocol}|#{k}"] = rule[k[2..]] rule[k[2..]] = null for k, v of rule continue unless v if k is 'after' or k is 'before' newrule[k] = iptables.normalize v, false continue k = "--#{k}" unless k[0..1] is '--' for mk, mvs of iptables.modules for mv in mvs if k is mv newrule["#{mk}|#{k}"] = v rule[k] = null for k, v of newrule continue if k is 'command' # Discard default log level value if k is '--log-level' and v is '4' delete newrule[k] continue # IPTables silently remove minus signs # v = v.replace '-', '' if /\-/.test v v = v.replace '-', '' if k is 'comment|--comment' v = jsesc v, quotes: 'double', wrap: true if ['--log-prefix', 'comment|--comment'].indexOf(k) isnt -1 newrule[k] = v newrules.push newrule if position and newrule.command isnt '-A' then for newrule in newrules # newrule.before = '-A': 'INPUT', chain: 'INPUT', '--jump': 'REJECT', '--reject-with': 'icmp-host-prohibited' unless newrule.after? or newrule.before? newrule.after = '-A': 'INPUT', chain: 'INPUT', '--jump': 'ACCEPT' unless newrule.after? or newrule.before? if Array.isArray rules then newrules else newrules[0] ### Parse the result of `iptables -S` ### parse: (stdout) -> rules = [] command_index = {} for line in string.lines stdout continue if line.length is 0 rule = {} i = 0 key = '' value = '' module = null while i <= line.length char = line[i] forceflush = i is line.length newarg = (i is 0 and char is '-') or line[(i-1)..i] is ' -' if newarg or forceflush if value value = value.trim() if key is '-m' module = value else key = "#{module}|#{key}" if module key = iptables.parameters_inverted[key] if iptables.parameters_inverted[key] rule[key] = value # First key is a command if iptables.commands_arguments[key] # Determine rule number if Array.isArray iptables.commands_arguments[key] rule.command = key for v, j in value.split ' ' rule[iptables.commands_arguments[key][j]] = v command_index[rule.chain] ?= 0 rule.rulenum = ++command_index[rule.chain] if ['-P', '-N'].indexOf(key) is -1 key = '' value = '' break if forceflush key += char while (char = line[++i]) isnt ' ' # and line[i]? key += char # if iptables.parameters.indexOf(key) isnt -1 if iptables.parameters_inverted[key] module = null continue if char is '"' while (char = line[++i]) isnt '"' value += char i++ continue while char+(char = line[++i]) isnt ' -' and i < line.length # IPTable silently remove minus sign from comment continue if char is '-' and key is '--comment' value += char rules.push rule rules