104 lines
2.7 KiB
TypeScript
104 lines
2.7 KiB
TypeScript
|
|
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();
|