Firewall added & some fixes
This commit is contained in:
98
handlers/rules.go
Normal file
98
handlers/rules.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"alpine-router/config"
|
||||
"alpine-router/firewall"
|
||||
"alpine-router/nat"
|
||||
"alpine-router/network"
|
||||
)
|
||||
|
||||
// applyAllRules rebuilds the complete nftables ruleset from the current config:
|
||||
// NAT masquerade + user firewall rules + VLAN isolation + blocked clients.
|
||||
func applyAllRules(cfg *config.AppConfig) error {
|
||||
if !nat.IsInstalled() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Collect blocked client IPs.
|
||||
var blockedIPs []string
|
||||
for _, kd := range cfg.KnownDevices {
|
||||
if kd.Blocked {
|
||||
ip := kd.IP
|
||||
if kd.StaticIP != "" {
|
||||
ip = kd.StaticIP
|
||||
}
|
||||
if ip != "" {
|
||||
blockedIPs = append(blockedIPs, ip)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build the LAN interface set for isolation:
|
||||
// all NAT interfaces + all VLAN interfaces (active + pending).
|
||||
// This ensures native interfaces (eth0) and their VLANs (eth0.100) are all
|
||||
// mutually isolated when VLANIsolation is enabled.
|
||||
seen := map[string]bool{}
|
||||
var lanIfaces []string
|
||||
addLAN := func(name string) {
|
||||
if name != "" && !seen[name] {
|
||||
lanIfaces = append(lanIfaces, name)
|
||||
seen[name] = true
|
||||
}
|
||||
}
|
||||
for _, name := range cfg.NAT.Interfaces {
|
||||
addLAN(name)
|
||||
}
|
||||
names, _ := network.GetInterfaces()
|
||||
for _, name := range names {
|
||||
if network.IsVLAN(name) {
|
||||
addLAN(name)
|
||||
addLAN(network.VLANParent(name)) // include parent (native VLAN) too
|
||||
}
|
||||
}
|
||||
for name := range network.GetAllPending() {
|
||||
if network.IsVLAN(name) {
|
||||
addLAN(name)
|
||||
addLAN(network.VLANParent(name))
|
||||
}
|
||||
}
|
||||
|
||||
// Convert config.FirewallRule → firewall.Rule.
|
||||
fwRules := make([]firewall.Rule, len(cfg.Firewall.Rules))
|
||||
for i, r := range cfg.Firewall.Rules {
|
||||
fwRules[i] = firewall.Rule{
|
||||
ID: r.ID,
|
||||
Enabled: r.Enabled,
|
||||
Action: r.Action,
|
||||
Protocol: r.Protocol,
|
||||
SrcAddr: r.SrcAddr,
|
||||
SrcPort: r.SrcPort,
|
||||
DstAddr: r.DstAddr,
|
||||
DstPort: r.DstPort,
|
||||
InIface: r.InIface,
|
||||
OutIface: r.OutIface,
|
||||
Comment: r.Comment,
|
||||
}
|
||||
}
|
||||
|
||||
return firewall.ApplyAll(
|
||||
firewall.NATConfig{Interfaces: cfg.NAT.Interfaces},
|
||||
firewall.Config{Rules: fwRules, VLANIsolation: cfg.Firewall.VLANIsolation},
|
||||
blockedIPs,
|
||||
lanIfaces,
|
||||
)
|
||||
}
|
||||
|
||||
// applyBlockedFirewall is the async helper called after client updates.
|
||||
func applyBlockedFirewall() {
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
log.Printf("Warning: load config for firewall: %v", err)
|
||||
return
|
||||
}
|
||||
if err := applyAllRules(cfg); err != nil {
|
||||
log.Printf("Warning: apply firewall rules: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user