14.04.2026 Update
This commit is contained in:
@@ -3,37 +3,77 @@ package handlers
|
||||
import (
|
||||
"log"
|
||||
|
||||
"alpine-router/config"
|
||||
"alpine-router/firewall"
|
||||
"alpine-router/nat"
|
||||
"alpine-router/network"
|
||||
"nano-router/clients"
|
||||
"nano-router/config"
|
||||
"nano-router/firewall"
|
||||
"nano-router/nat"
|
||||
"nano-router/network"
|
||||
)
|
||||
|
||||
// resolveClientPolicy returns the effective routing policy for a device.
|
||||
// Explicit per-device Policy takes priority; then legacy Blocked flag; then default.
|
||||
func resolveClientPolicy(kd config.KnownDevice, defaultPolicy string) string {
|
||||
if kd.Policy != "" {
|
||||
return kd.Policy
|
||||
}
|
||||
if kd.Blocked {
|
||||
return "disabled"
|
||||
}
|
||||
if defaultPolicy != "" {
|
||||
return defaultPolicy
|
||||
}
|
||||
return "direct"
|
||||
}
|
||||
|
||||
// applyAllRules rebuilds the complete nftables ruleset from the current config:
|
||||
// NAT masquerade + user firewall rules + VLAN isolation + blocked clients.
|
||||
// NAT masquerade + tproxy for VPN clients + disabled client drops +
|
||||
// user firewall rules + VLAN isolation.
|
||||
func applyAllRules(cfg *config.AppConfig) error {
|
||||
if !nat.IsInstalled() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Collect blocked client IPs.
|
||||
var blockedIPs []string
|
||||
defaultPolicy := cfg.ClientPolicy.Default
|
||||
if defaultPolicy == "" {
|
||||
defaultPolicy = "direct"
|
||||
}
|
||||
|
||||
// Classify each known device into disabled or vpn buckets.
|
||||
// For devices connected on multiple interfaces (same MAC, different IPs)
|
||||
// we also include all live ARP IPs so every interface gets the same policy.
|
||||
arpByMAC := clients.GetARPIPsByMAC()
|
||||
seenIP := make(map[string]bool)
|
||||
var disabledIPs, vpnIPs []string
|
||||
|
||||
addIP := func(ip, policy string) {
|
||||
if ip == "" || seenIP[ip] {
|
||||
return
|
||||
}
|
||||
seenIP[ip] = true
|
||||
switch policy {
|
||||
case "disabled":
|
||||
disabledIPs = append(disabledIPs, ip)
|
||||
case "vpn":
|
||||
vpnIPs = append(vpnIPs, ip)
|
||||
}
|
||||
}
|
||||
|
||||
for _, kd := range cfg.KnownDevices {
|
||||
if kd.Blocked {
|
||||
ip := kd.IP
|
||||
if kd.StaticIP != "" {
|
||||
ip = kd.StaticIP
|
||||
}
|
||||
if ip != "" {
|
||||
blockedIPs = append(blockedIPs, ip)
|
||||
}
|
||||
policy := resolveClientPolicy(kd, defaultPolicy)
|
||||
// Primary stored IP.
|
||||
ip := kd.IP
|
||||
if kd.StaticIP != "" {
|
||||
ip = kd.StaticIP
|
||||
}
|
||||
addIP(ip, policy)
|
||||
// All other IPs this MAC currently has in the ARP table.
|
||||
for _, arpIP := range arpByMAC[kd.MAC] {
|
||||
addIP(arpIP, policy)
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
@@ -49,7 +89,7 @@ func applyAllRules(cfg *config.AppConfig) error {
|
||||
for _, name := range names {
|
||||
if network.IsVLAN(name) {
|
||||
addLAN(name)
|
||||
addLAN(network.VLANParent(name)) // include parent (native VLAN) too
|
||||
addLAN(network.VLANParent(name))
|
||||
}
|
||||
}
|
||||
for name := range network.GetAllPending() {
|
||||
@@ -80,12 +120,15 @@ func applyAllRules(cfg *config.AppConfig) error {
|
||||
return firewall.ApplyAll(
|
||||
firewall.NATConfig{Interfaces: cfg.NAT.Interfaces},
|
||||
firewall.Config{Rules: fwRules, VLANIsolation: cfg.Firewall.VLANIsolation},
|
||||
blockedIPs,
|
||||
lanIfaces,
|
||||
firewall.ClientPolicies{
|
||||
DisabledIPs: disabledIPs,
|
||||
VPNIPs: vpnIPs,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// applyBlockedFirewall is the async helper called after client updates.
|
||||
// applyBlockedFirewall is the async helper called after client or policy updates.
|
||||
func applyBlockedFirewall() {
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user