|
|
@ -164,32 +164,38 @@ export const firewall = { |
|
|
/** |
|
|
/** |
|
|
* Initialize the custom chain if it doesn't exist |
|
|
* Initialize the custom chain if it doesn't exist |
|
|
*/ |
|
|
*/ |
|
|
async initChain(interfaceName: string): Promise<void> { |
|
|
async initChain(interfaceName: string, enableIpv6: boolean): Promise<void> { |
|
|
FW_DEBUG( |
|
|
FW_DEBUG( |
|
|
`Initializing firewall chain ${CHAIN_NAME} for interface ${interfaceName}` |
|
|
`Initializing firewall chain ${CHAIN_NAME} for interface ${interfaceName}` |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
// Create chain if not exists (iptables returns error if exists, so we ignore)
|
|
|
// Create chain if not exists (iptables returns error if exists, so we ignore)
|
|
|
await exec(`iptables -N ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
await exec(`iptables -N ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
|
|
|
if (enableIpv6) { |
|
|
await exec(`ip6tables -N ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
await exec(`ip6tables -N ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// Ensure chain is referenced from FORWARD (if not already)
|
|
|
// Ensure chain is referenced from FORWARD (if not already)
|
|
|
// Insert at position 1 to process before generic ACCEPT rules
|
|
|
// Insert at position 1 to process before generic ACCEPT rules
|
|
|
await exec( |
|
|
await exec( |
|
|
`iptables -C FORWARD -i ${interfaceName} -j ${CHAIN_NAME} 2>/dev/null || iptables -I FORWARD 1 -i ${interfaceName} -j ${CHAIN_NAME}` |
|
|
`iptables -C FORWARD -i ${interfaceName} -j ${CHAIN_NAME} 2>/dev/null || iptables -I FORWARD 1 -i ${interfaceName} -j ${CHAIN_NAME}` |
|
|
); |
|
|
); |
|
|
|
|
|
if (enableIpv6) { |
|
|
await exec( |
|
|
await exec( |
|
|
`ip6tables -C FORWARD -i ${interfaceName} -j ${CHAIN_NAME} 2>/dev/null || ip6tables -I FORWARD 1 -i ${interfaceName} -j ${CHAIN_NAME}` |
|
|
`ip6tables -C FORWARD -i ${interfaceName} -j ${CHAIN_NAME} 2>/dev/null || ip6tables -I FORWARD 1 -i ${interfaceName} -j ${CHAIN_NAME}` |
|
|
); |
|
|
); |
|
|
|
|
|
} |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Flush all rules in the custom chain |
|
|
* Flush all rules in the custom chain |
|
|
*/ |
|
|
*/ |
|
|
async flushChain(): Promise<void> { |
|
|
async flushChain(enableIpv6: boolean): Promise<void> { |
|
|
FW_DEBUG(`Flushing firewall chain ${CHAIN_NAME}`); |
|
|
FW_DEBUG(`Flushing firewall chain ${CHAIN_NAME}`); |
|
|
await exec(`iptables -F ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
await exec(`iptables -F ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
|
|
|
if (enableIpv6) { |
|
|
await exec(`ip6tables -F ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
await exec(`ip6tables -F ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
|
|
|
} |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
@ -245,7 +251,7 @@ export const firewall = { |
|
|
): Promise<void> { |
|
|
): Promise<void> { |
|
|
if (!wgInterface.firewallEnabled) { |
|
|
if (!wgInterface.firewallEnabled) { |
|
|
FW_DEBUG('Firewall filtering disabled, removing any existing rules'); |
|
|
FW_DEBUG('Firewall filtering disabled, removing any existing rules'); |
|
|
await this.removeFiltering(wgInterface.name); |
|
|
await this.removeFiltering(wgInterface.name, enableIpv6); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -262,10 +268,10 @@ export const firewall = { |
|
|
FW_DEBUG('Rebuilding firewall rules...'); |
|
|
FW_DEBUG('Rebuilding firewall rules...'); |
|
|
|
|
|
|
|
|
// Initialize chain structure
|
|
|
// Initialize chain structure
|
|
|
await this.initChain(wgInterface.name); |
|
|
await this.initChain(wgInterface.name, enableIpv6); |
|
|
|
|
|
|
|
|
// Flush existing rules
|
|
|
// Flush existing rules
|
|
|
await this.flushChain(); |
|
|
await this.flushChain(enableIpv6); |
|
|
|
|
|
|
|
|
// Apply rules for each enabled client
|
|
|
// Apply rules for each enabled client
|
|
|
for (const client of clients) { |
|
|
for (const client of clients) { |
|
|
@ -299,22 +305,26 @@ export const firewall = { |
|
|
/** |
|
|
/** |
|
|
* Remove all firewall filtering (when feature is disabled) |
|
|
* Remove all firewall filtering (when feature is disabled) |
|
|
*/ |
|
|
*/ |
|
|
async removeFiltering(interfaceName: string): Promise<void> { |
|
|
async removeFiltering(interfaceName: string, enableIpv6: boolean): Promise<void> { |
|
|
FW_DEBUG(`Removing firewall filtering for interface ${interfaceName}`); |
|
|
FW_DEBUG(`Removing firewall filtering for interface ${interfaceName}`); |
|
|
|
|
|
|
|
|
// Remove jump rules from FORWARD chain
|
|
|
// Remove jump rules from FORWARD chain
|
|
|
await exec( |
|
|
await exec( |
|
|
`iptables -D FORWARD -i ${interfaceName} -j ${CHAIN_NAME} 2>/dev/null || true` |
|
|
`iptables -D FORWARD -i ${interfaceName} -j ${CHAIN_NAME} 2>/dev/null || true` |
|
|
); |
|
|
); |
|
|
|
|
|
if (enableIpv6) { |
|
|
await exec( |
|
|
await exec( |
|
|
`ip6tables -D FORWARD -i ${interfaceName} -j ${CHAIN_NAME} 2>/dev/null || true` |
|
|
`ip6tables -D FORWARD -i ${interfaceName} -j ${CHAIN_NAME} 2>/dev/null || true` |
|
|
); |
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// Flush and delete the chain
|
|
|
// Flush and delete the chain
|
|
|
await exec(`iptables -F ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
await exec(`iptables -F ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
await exec(`ip6tables -F ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
|
|
|
await exec(`iptables -X ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
await exec(`iptables -X ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
|
|
|
if (enableIpv6) { |
|
|
|
|
|
await exec(`ip6tables -F ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
await exec(`ip6tables -X ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
await exec(`ip6tables -X ${CHAIN_NAME} 2>/dev/null || true`); |
|
|
|
|
|
} |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
|