83 lines
2.1 KiB
TypeScript
83 lines
2.1 KiB
TypeScript
import type { TNftFamily, TNftProtocol, INftDnatRule, INftSnatRule, INftMasqueradeRule } from './nft.types.js';
|
|
|
|
/**
|
|
* Expand a protocol spec into concrete protocol strings.
|
|
*/
|
|
function expandProtocols(protocol?: TNftProtocol): string[] {
|
|
switch (protocol ?? 'tcp') {
|
|
case 'tcp': return ['tcp'];
|
|
case 'udp': return ['udp'];
|
|
case 'both': return ['tcp', 'udp'];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build DNAT rules for port forwarding.
|
|
* Generates DNAT + optional masquerade for each protocol.
|
|
* Direct port of Rust build_dnat_rule.
|
|
*/
|
|
export function buildDnatRules(
|
|
tableName: string,
|
|
family: TNftFamily,
|
|
rule: INftDnatRule,
|
|
): string[] {
|
|
const protocols = expandProtocols(rule.protocol);
|
|
const commands: string[] = [];
|
|
|
|
for (const proto of protocols) {
|
|
// DNAT rule
|
|
commands.push(
|
|
`nft add rule ${family} ${tableName} prerouting ${proto} dport ${rule.sourcePort} dnat to ${rule.targetHost}:${rule.targetPort}`
|
|
);
|
|
|
|
// Masquerade (SNAT) unless preserveSourceIP is set
|
|
if (!rule.preserveSourceIP) {
|
|
commands.push(
|
|
`nft add rule ${family} ${tableName} postrouting ${proto} dport ${rule.targetPort} masquerade`
|
|
);
|
|
}
|
|
}
|
|
|
|
return commands;
|
|
}
|
|
|
|
/**
|
|
* Build an SNAT rule to rewrite source address.
|
|
*/
|
|
export function buildSnatRule(
|
|
tableName: string,
|
|
family: TNftFamily,
|
|
rule: INftSnatRule,
|
|
): string[] {
|
|
const protocols = expandProtocols(rule.protocol);
|
|
const commands: string[] = [];
|
|
|
|
for (const proto of protocols) {
|
|
commands.push(
|
|
`nft add rule ${family} ${tableName} postrouting ${proto} dport ${rule.targetPort} snat to ${rule.sourceAddress}`
|
|
);
|
|
}
|
|
|
|
return commands;
|
|
}
|
|
|
|
/**
|
|
* Build a masquerade rule for outgoing NAT.
|
|
*/
|
|
export function buildMasqueradeRule(
|
|
tableName: string,
|
|
family: TNftFamily,
|
|
rule: INftMasqueradeRule,
|
|
): string[] {
|
|
const protocols = expandProtocols(rule.protocol);
|
|
const commands: string[] = [];
|
|
|
|
for (const proto of protocols) {
|
|
commands.push(
|
|
`nft add rule ${family} ${tableName} postrouting ${proto} dport ${rule.targetPort} masquerade`
|
|
);
|
|
}
|
|
|
|
return commands;
|
|
}
|