feat(nft): add source IP filtering for DNAT rules and expose table existence checks
This commit is contained in:
@@ -1,5 +1,12 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-03-30 - 1.1.0 - feat(nft)
|
||||||
|
add source IP filtering for DNAT rules and expose table existence checks
|
||||||
|
|
||||||
|
- Adds an optional sourceIP field to NAT rule definitions to restrict DNAT rules to matching source addresses or subnets.
|
||||||
|
- Updates DNAT rule generation to include an ip saddr match when sourceIP is provided.
|
||||||
|
- Introduces a tableExists() manager method to detect whether the managed nftables table is still present in the kernel.
|
||||||
|
|
||||||
## 2026-03-26 - 1.0.1 - fix(repo)
|
## 2026-03-26 - 1.0.1 - fix(repo)
|
||||||
no changes to commit
|
no changes to commit
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@push.rocks/smartnftables',
|
name: '@push.rocks/smartnftables',
|
||||||
version: '1.0.1',
|
version: '1.1.0',
|
||||||
description: 'A TypeScript module for managing nftables rules including NAT, firewall, and rate limiting with a high-level API.'
|
description: 'A TypeScript module for managing nftables rules including NAT, firewall, and rate limiting with a high-level API.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,6 +133,22 @@ export class SmartNftables {
|
|||||||
this.hasFilterChains = false;
|
this.hasFilterChains = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the managed nftables table exists in the kernel.
|
||||||
|
* Returns false if not root, not initialized, or the table was removed externally.
|
||||||
|
*/
|
||||||
|
public async tableExists(): Promise<boolean> {
|
||||||
|
if (!this.executor.isRoot() || !this.initialized) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await this.executor.exec(`nft list table ${this.family} ${this.tableName}`);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get status report of the managed nftables state.
|
* Get status report of the managed nftables state.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -26,8 +26,9 @@ export function buildDnatRules(
|
|||||||
|
|
||||||
for (const proto of protocols) {
|
for (const proto of protocols) {
|
||||||
// DNAT rule
|
// DNAT rule
|
||||||
|
const saddrFilter = rule.sourceIP ? `ip saddr ${rule.sourceIP} ` : '';
|
||||||
commands.push(
|
commands.push(
|
||||||
`nft add rule ${family} ${tableName} prerouting ${proto} dport ${rule.sourcePort} dnat to ${rule.targetHost}:${rule.targetPort}`
|
`nft add rule ${family} ${tableName} prerouting ${saddrFilter}${proto} dport ${rule.sourcePort} dnat to ${rule.targetHost}:${rule.targetPort}`
|
||||||
);
|
);
|
||||||
|
|
||||||
// Masquerade (SNAT) unless preserveSourceIP is set
|
// Masquerade (SNAT) unless preserveSourceIP is set
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ export interface INftDnatRule {
|
|||||||
targetPort: number;
|
targetPort: number;
|
||||||
protocol?: TNftProtocol;
|
protocol?: TNftProtocol;
|
||||||
preserveSourceIP?: boolean;
|
preserveSourceIP?: boolean;
|
||||||
|
/** Filter by source IP/subnet (e.g. '10.8.0.0/24'). Only matching traffic gets DNAT'd. */
|
||||||
|
sourceIP?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface INftSnatRule {
|
export interface INftSnatRule {
|
||||||
|
|||||||
Reference in New Issue
Block a user