forked from Deuxfleurs/infrastructure
53 lines
1.6 KiB
JavaScript
53 lines
1.6 KiB
JavaScript
'use strict'
|
|
|
|
let l;
|
|
export default l = async (path, readFile, exec, log) => {
|
|
|
|
const load_static_rules = async path =>
|
|
(await readFile(path, 'utf-8'))
|
|
.split('\n')
|
|
.filter(e => e)
|
|
|
|
const get_current_rules = async () =>
|
|
(await exec('iptables -S INPUT'))
|
|
.stdout
|
|
.split('\n')
|
|
.filter(e => e.match(/^-A INPUT/g))
|
|
|
|
const compute_rules_to_add = (current, target) =>
|
|
target.filter(r => !current.includes(r))
|
|
|
|
const compute_rules_to_del = (current, target) =>
|
|
current
|
|
.filter(r => !target.includes(r))
|
|
.map(r => r.replace(/^-A INPUT/g, '-D INPUT'))
|
|
|
|
const update_rules = async (current, target) =>
|
|
await Promise.all([
|
|
...compute_rules_to_del(current, target),
|
|
...compute_rules_to_add(current, target)
|
|
].map(r => exec(`iptables ${r}`)))
|
|
|
|
const build_target_rules = (tag_list) =>
|
|
tag_list
|
|
.map(t => /^public_port=(\d+)(-(\d+))?\/(udp|tcp)/g.exec(t))
|
|
.filter(t => t)
|
|
.map(t => new Object({ start: t[1], stop: t[3], protocol: t[4] }))
|
|
.map(t => t.stop
|
|
? `-A INPUT -p ${t.protocol} --match multiport --dports ${t.start}:${t.stop} -j ACCEPT`
|
|
: `-A INPUT -p ${t.protocol} --dport ${t.start} -j ACCEPT`)
|
|
|
|
const do_log = (tag_list, r) => {
|
|
//log('[iptables]', tag_list)
|
|
log(`[iptables] ran ${r.length} commands`)
|
|
}
|
|
|
|
const static_rules = path ? await load_static_rules(path) : []
|
|
log(`[iptables] initialized with ${static_rules.length} static rules`)
|
|
return async tag_list =>
|
|
do_log(
|
|
tag_list,
|
|
await update_rules(
|
|
await get_current_rules(),
|
|
[...static_rules, ...build_target_rules(tag_list)]))
|
|
}
|