Firewall added & some fixes

This commit is contained in:
MoonDev
2026-04-13 12:40:49 +03:00
parent 7eaa9750b0
commit 8c35022483
22 changed files with 1659 additions and 134 deletions

View File

@@ -72,6 +72,13 @@ func ApplyPending() map[string]error {
ClearPendingConfig(name)
continue
}
// For VLAN interfaces ensure the kernel interface exists before ifup.
if IsVLAN(name) {
if err := EnsureVLANExists(name); err != nil {
errs[name] = err
continue
}
}
_ = IfDown(name)
if cfg := configs[name]; cfg != nil && cfg.Auto {
if err := IfUp(name); err != nil {

View File

@@ -13,6 +13,7 @@ const ConfigFile = "/etc/network/interfaces"
// InterfaceConfig represents one stanza in /etc/network/interfaces.
type InterfaceConfig struct {
Name string `json:"name"`
Label string `json:"label,omitempty"` // display name, stored in config.yaml only
Auto bool `json:"auto"`
Mode string `json:"mode"` // dhcp, static, loopback, manual
Address string `json:"address,omitempty"` // static only
@@ -154,12 +155,18 @@ func WriteConfig(configs map[string]*InterfaceConfig) error {
}
defer f.Close()
// loopback first
// loopback first, then physical interfaces, then VLANs (sorted within each group)
if lo, ok := configs["lo"]; ok {
writeStanza(f, lo)
}
for name, cfg := range configs {
if name == "lo" {
if name == "lo" || IsVLAN(name) {
continue
}
writeStanza(f, cfg)
}
for name, cfg := range configs {
if !IsVLAN(name) {
continue
}
writeStanza(f, cfg)
@@ -188,6 +195,12 @@ func writeStanza(f *os.File, c *InterfaceConfig) {
fmt.Fprintf(f, "\tdns-nameservers %s\n", strings.Join(c.DNS, " "))
}
}
// VLAN interfaces need vlan-raw-device unless already in Extra
if IsVLAN(c.Name) {
if _, ok := c.Extra["vlan-raw-device"]; !ok {
fmt.Fprintf(f, "\tvlan-raw-device %s\n", VLANParent(c.Name))
}
}
for k, v := range c.Extra {
fmt.Fprintf(f, "\t%s %s\n", k, v)
}

80
network/vlan.go Normal file
View File

@@ -0,0 +1,80 @@
package network
import (
"fmt"
"os"
"os/exec"
"strconv"
"strings"
)
// IsVLAN reports whether name is a VLAN interface (e.g. "eth0.100").
func IsVLAN(name string) bool {
idx := strings.LastIndex(name, ".")
if idx <= 0 {
return false
}
suffix := name[idx+1:]
if suffix == "" {
return false
}
_, err := strconv.Atoi(suffix)
return err == nil
}
// VLANParent returns the parent interface (e.g. "eth0.100" → "eth0").
func VLANParent(name string) string {
idx := strings.LastIndex(name, ".")
if idx < 0 {
return ""
}
return name[:idx]
}
// VLANId returns the VLAN ID (e.g. "eth0.100" → 100).
func VLANId(name string) int {
idx := strings.LastIndex(name, ".")
if idx < 0 {
return 0
}
id, _ := strconv.Atoi(name[idx+1:])
return id
}
// EnsureVLANExists creates the VLAN interface in the kernel if it doesn't exist.
func EnsureVLANExists(name string) error {
if _, err := os.Stat("/sys/class/net/" + name); err == nil {
return nil
}
parent := VLANParent(name)
id := VLANId(name)
if parent == "" || id == 0 {
return fmt.Errorf("invalid VLAN name: %s", name)
}
out, err := exec.Command("ip", "link", "add", "link", parent,
"name", name, "type", "vlan", "id", strconv.Itoa(id)).CombinedOutput()
if err != nil {
return fmt.Errorf("ip link add %s: %s", name, strings.TrimSpace(string(out)))
}
return nil
}
// DeleteVLAN brings down and removes a VLAN interface and its /etc/network/interfaces stanza.
func DeleteVLAN(name string) error {
_ = IfDown(name)
if _, err := os.Stat("/sys/class/net/" + name); err == nil {
out, err2 := exec.Command("ip", "link", "delete", name).CombinedOutput()
if err2 != nil {
return fmt.Errorf("ip link delete %s: %s", name, strings.TrimSpace(string(out)))
}
}
configs, err := ParseConfig()
if err != nil {
return err
}
if _, ok := configs[name]; ok {
delete(configs, name)
return WriteConfig(configs)
}
return nil
}