import { tap, expect } from '@git.zone/tstest/tapbundle'; import { buildDnatRules, buildSnatRule, buildMasqueradeRule, } from '../ts/nft.rulebuilder.nat.js'; tap.test('should build basic DNAT rule with masquerade', async () => { const rules = buildDnatRules('mytable', 'ip', { sourcePort: 443, targetHost: '10.0.0.1', targetPort: 8443, }); expect(rules.length).toEqual(2); expect(rules[0]).toInclude('dnat to 10.0.0.1:8443'); expect(rules[0]).toInclude('dport 443'); expect(rules[0]).toInclude('tcp'); expect(rules[1]).toInclude('masquerade'); expect(rules[1]).toInclude('dport 8443'); }); tap.test('should skip masquerade when preserveSourceIP is true', async () => { const rules = buildDnatRules('mytable', 'ip', { sourcePort: 443, targetHost: '10.0.0.1', targetPort: 8443, preserveSourceIP: true, }); expect(rules.length).toEqual(1); expect(rules[0]).toInclude('dnat to 10.0.0.1:8443'); for (const r of rules) { expect(r).not.toInclude('masquerade'); } }); tap.test('should generate TCP and UDP rules for protocol both', async () => { const rules = buildDnatRules('mytable', 'ip', { sourcePort: 53, targetHost: '10.0.0.53', targetPort: 53, protocol: 'both', }); // TCP DNAT + masquerade + UDP DNAT + masquerade = 4 expect(rules.length).toEqual(4); const tcpRules = rules.filter(r => r.includes('tcp')); const udpRules = rules.filter(r => r.includes('udp')); expect(tcpRules.length).toEqual(2); expect(udpRules.length).toEqual(2); }); tap.test('should generate UDP-only rules', async () => { const rules = buildDnatRules('mytable', 'ip', { sourcePort: 53, targetHost: '10.0.0.53', targetPort: 53, protocol: 'udp', }); for (const r of rules) { expect(r).not.toInclude('tcp'); } expect(rules.some(r => r.includes('udp dport 53 dnat'))).toBeTrue(); }); tap.test('should build SNAT rule', async () => { const rules = buildSnatRule('mytable', 'ip', { sourceAddress: '192.168.1.1', targetPort: 80, }); expect(rules.length).toEqual(1); expect(rules[0]).toInclude('snat to 192.168.1.1'); expect(rules[0]).toInclude('dport 80'); }); tap.test('should build masquerade rule', async () => { const rules = buildMasqueradeRule('mytable', 'ip', { targetPort: 8080, protocol: 'both', }); expect(rules.length).toEqual(2); expect(rules[0]).toInclude('tcp'); expect(rules[0]).toInclude('masquerade'); expect(rules[1]).toInclude('udp'); }); tap.test('should use correct family in commands', async () => { const rules = buildDnatRules('mytable', 'inet', { sourcePort: 80, targetHost: '10.0.0.1', targetPort: 8080, }); for (const r of rules) { expect(r).toInclude('inet mytable'); } }); export default tap.start();