all: add firewalla support

This commit is contained in:
Cuong Manh Le
2023-08-09 23:54:23 +07:00
committed by Cuong Manh Le
parent 03781d4cec
commit 350d8355b1
5 changed files with 188 additions and 38 deletions
+7
View File
@@ -26,6 +26,13 @@ func setDependencies(svc *service.Config) {
svc.Dependencies = append(svc.Dependencies, "Wants=dnsmasq.service") svc.Dependencies = append(svc.Dependencies, "Wants=dnsmasq.service")
svc.Dependencies = append(svc.Dependencies, "After=dnsmasq.service") svc.Dependencies = append(svc.Dependencies, "After=dnsmasq.service")
} }
// On Firewalla, ctrld needs to start after firerouter_{dhcp,dns}, so it can read leases file.
if router.Name() == router.Firewalla {
svc.Dependencies = append(svc.Dependencies, "Wants=firerouter_dhcp.service")
svc.Dependencies = append(svc.Dependencies, "After=firerouter_dhcp.service")
svc.Dependencies = append(svc.Dependencies, "Wants=firerouter_dns.service")
svc.Dependencies = append(svc.Dependencies, "After=firerouter_dns.service")
}
} }
func setWorkingDirectory(svc *service.Config, dir string) { func setWorkingDirectory(svc *service.Config, dir string) {
+11 -10
View File
@@ -21,16 +21,17 @@ type readClientInfoFunc func(name string) error
// clientInfoFiles specifies client info files and how to read them on supported platforms. // clientInfoFiles specifies client info files and how to read them on supported platforms.
var clientInfoFiles = map[string]readClientInfoFunc{ var clientInfoFiles = map[string]readClientInfoFunc{
"/tmp/dnsmasq.leases": dnsmasqReadClientInfoFile, // ddwrt "/tmp/dnsmasq.leases": dnsmasqReadClientInfoFile, // ddwrt
"/tmp/dhcp.leases": dnsmasqReadClientInfoFile, // openwrt "/tmp/dhcp.leases": dnsmasqReadClientInfoFile, // openwrt
"/var/lib/misc/dnsmasq.leases": dnsmasqReadClientInfoFile, // merlin "/var/lib/misc/dnsmasq.leases": dnsmasqReadClientInfoFile, // merlin
"/mnt/data/udapi-config/dnsmasq.lease": dnsmasqReadClientInfoFile, // UDM Pro "/mnt/data/udapi-config/dnsmasq.lease": dnsmasqReadClientInfoFile, // UDM Pro
"/data/udapi-config/dnsmasq.lease": dnsmasqReadClientInfoFile, // UDR "/data/udapi-config/dnsmasq.lease": dnsmasqReadClientInfoFile, // UDR
"/etc/dhcpd/dhcpd-leases.log": dnsmasqReadClientInfoFile, // Synology "/etc/dhcpd/dhcpd-leases.log": dnsmasqReadClientInfoFile, // Synology
"/tmp/var/lib/misc/dnsmasq.leases": dnsmasqReadClientInfoFile, // Tomato "/tmp/var/lib/misc/dnsmasq.leases": dnsmasqReadClientInfoFile, // Tomato
"/run/dnsmasq-dhcp.leases": dnsmasqReadClientInfoFile, // EdgeOS "/run/dnsmasq-dhcp.leases": dnsmasqReadClientInfoFile, // EdgeOS
"/run/dhcpd.leases": iscDHCPReadClientInfoFile, // EdgeOS "/run/dhcpd.leases": iscDHCPReadClientInfoFile, // EdgeOS
"/var/dhcpd/var/db/dhcpd.leases": iscDHCPReadClientInfoFile, // Pfsense "/var/dhcpd/var/db/dhcpd.leases": iscDHCPReadClientInfoFile, // Pfsense
"/home/pi/.router/run/dhcp/dnsmasq.leases": dnsmasqReadClientInfoFile, // Firewalla
} }
// watchClientInfoTable watches changes happens in dnsmasq/dhcpd // watchClientInfoTable watches changes happens in dnsmasq/dhcpd
+8 -3
View File
@@ -1,6 +1,7 @@
package router package router
import ( import (
"fmt"
"strings" "strings"
"text/template" "text/template"
) )
@@ -49,8 +50,10 @@ func dnsMasqConf() (string, error) {
var sb strings.Builder var sb strings.Builder
var tmplText string var tmplText string
switch Name() { switch Name() {
case EdgeOS, DDWrt, OpenWrt, Ubios, Synology, Tomato: case DDWrt, EdgeOS, OpenWrt, Ubios, Synology, Tomato:
tmplText = dnsMasqConfigContentTmpl tmplText = dnsMasqConfigContentTmpl
case Firewalla:
tmplText = dnsMasqConfigContentTmpl + fmt.Sprintf("listen-address=127.0.0.1\n")
case Merlin: case Merlin:
tmplText = merlinDNSMasqPostConfTmpl tmplText = merlinDNSMasqPostConfTmpl
} }
@@ -68,10 +71,12 @@ func dnsMasqConf() (string, error) {
func restartDNSMasq() error { func restartDNSMasq() error {
switch Name() { switch Name() {
case EdgeOS:
return edgeOSRestartDNSMasq()
case DDWrt: case DDWrt:
return ddwrtRestartDNSMasq() return ddwrtRestartDNSMasq()
case EdgeOS:
return edgeOSRestartDNSMasq()
case Firewalla:
return firewallaRestartDNSMasq()
case Merlin: case Merlin:
return merlinRestartDNSMasq() return merlinRestartDNSMasq()
case OpenWrt: case OpenWrt:
+103
View File
@@ -0,0 +1,103 @@
package router
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
)
const (
firewallaDNSMasqConfigPath = "/home/pi/.firewalla/config/dnsmasq_local"
firewallaDNSMasqBackupConfigPath = "/home/pi/.firewalla/config/dnsmasq_local.bak"
firewallaConfigPostMainDir = "/home/pi/.firewalla/config/post_main.d"
firewallaCtrldInitScriptPath = "/home/pi/.firewalla/config/post_main.d/start_ctrld.sh"
)
func setupFirewalla() error {
fi, err := os.Stat(firewallaDNSMasqConfigPath)
if err != nil {
return fmt.Errorf("setupFirewalla: get current config directory: %w", err)
}
_ = os.RemoveAll(firewallaDNSMasqBackupConfigPath)
// Creating a backup.
if err := os.Rename(firewallaDNSMasqConfigPath, firewallaDNSMasqBackupConfigPath); err != nil {
return fmt.Errorf("setupFirewalla: backup current config: %w", err)
}
// Creating our own config.
if err := os.MkdirAll(firewallaDNSMasqConfigPath, fi.Mode()); err != nil {
return fmt.Errorf("setupFirewalla: creating config dir: %w", err)
}
// Adding ctrld listener as the only upstream.
dnsMasqConfigContent, err := dnsMasqConf()
if err != nil {
return fmt.Errorf("setupFirewalla: generating dnsmasq config: %w", err)
}
ctrldConfPath := filepath.Join(firewallaDNSMasqConfigPath, "ctrld")
if err := os.WriteFile(ctrldConfPath, []byte(dnsMasqConfigContent), 0600); err != nil {
return fmt.Errorf("setupFirewalla: writing ctrld config: %w", err)
}
// Restart dnsmasq service.
if err := restartDNSMasq(); err != nil {
return fmt.Errorf("setupFirewalla: restartDNSMasq: %w", err)
}
return nil
}
func cleanupFirewalla() error {
// Do nothing if there's no backup config.
if _, err := os.Stat(firewallaDNSMasqBackupConfigPath); err != nil && os.IsNotExist(err) {
return nil
}
// Removing current config.
if err := os.RemoveAll(firewallaDNSMasqConfigPath); err != nil {
return fmt.Errorf("cleanupFirewalla: removing ctrld config: %w", err)
}
// Restoring backup.
if err := os.Rename(firewallaDNSMasqBackupConfigPath, firewallaDNSMasqConfigPath); err != nil {
return fmt.Errorf("cleanupFirewalla: restoring backup config: %w", err)
}
// Restart dnsmasq service.
if err := restartDNSMasq(); err != nil {
return fmt.Errorf("cleaupFirewalla: restartDNSMasq: %w", err)
}
return nil
}
func postInstallFirewalla() error {
// Writing startup script.
if err := writeFirewallStartupScript(); err != nil {
return fmt.Errorf("postInstallFirewalla: writing startup script: %w", err)
}
return nil
}
func firewallaRestartDNSMasq() error {
return exec.Command("systemctl", "restart", "firerouter_dns").Run()
}
func writeFirewallStartupScript() error {
if err := os.MkdirAll(firewallaConfigPostMainDir, 0775); err != nil {
return err
}
exe, err := os.Executable()
if err != nil {
return err
}
// This is called when "ctrld start ..." runs, so recording
// the same command line arguments to use in startup script.
argStr := strings.Join(os.Args[1:], " ")
script := fmt.Sprintf("#!/bin/bash\n\nsudo %q %s\n", exe, argStr)
return os.WriteFile(firewallaCtrldInitScriptPath, []byte(script), 0755)
}
+59 -25
View File
@@ -19,14 +19,15 @@ import (
) )
const ( const (
OpenWrt = "openwrt" DDWrt = "ddwrt"
DDWrt = "ddwrt" EdgeOS = "edgeos"
Merlin = "merlin" Firewalla = "firewalla"
Ubios = "ubios" Merlin = "merlin"
Synology = "synology" OpenWrt = "openwrt"
Tomato = "tomato" Pfsense = "pfsense"
EdgeOS = "edgeos" Synology = "synology"
Pfsense = "pfsense" Tomato = "tomato"
Ubios = "ubios"
) )
// ErrNotSupported reports the current router is not supported error. // ErrNotSupported reports the current router is not supported error.
@@ -44,7 +45,15 @@ type router struct {
// IsSupported reports whether the given platform is supported by ctrld. // IsSupported reports whether the given platform is supported by ctrld.
func IsSupported(platform string) bool { func IsSupported(platform string) bool {
switch platform { switch platform {
case EdgeOS, DDWrt, Merlin, OpenWrt, Pfsense, Synology, Tomato, Ubios: case DDWrt,
EdgeOS,
Firewalla,
Merlin,
OpenWrt,
Pfsense,
Synology,
Tomato,
Ubios:
return true return true
} }
return false return false
@@ -52,25 +61,44 @@ func IsSupported(platform string) bool {
// SupportedPlatforms return all platforms that can be configured to run with ctrld. // SupportedPlatforms return all platforms that can be configured to run with ctrld.
func SupportedPlatforms() []string { func SupportedPlatforms() []string {
return []string{EdgeOS, DDWrt, Merlin, OpenWrt, Pfsense, Synology, Tomato, Ubios} return []string{
DDWrt,
EdgeOS,
Firewalla,
Merlin,
OpenWrt,
Pfsense,
Synology,
Tomato,
Ubios,
}
} }
var configureFunc = map[string]func() error{ var configureFunc = map[string]func() error{
EdgeOS: setupEdgeOS, DDWrt: setupDDWrt,
DDWrt: setupDDWrt, EdgeOS: setupEdgeOS,
Merlin: setupMerlin, Firewalla: setupFirewalla,
OpenWrt: setupOpenWrt, Merlin: setupMerlin,
Pfsense: setupPfsense, OpenWrt: setupOpenWrt,
Synology: setupSynology, Pfsense: setupPfsense,
Tomato: setupTomato, Synology: setupSynology,
Ubios: setupUbiOS, Tomato: setupTomato,
Ubios: setupUbiOS,
} }
// Configure configures things for running ctrld on the router. // Configure configures things for running ctrld on the router.
func Configure(c *ctrld.Config) error { func Configure(c *ctrld.Config) error {
name := Name() name := Name()
switch name { switch name {
case EdgeOS, DDWrt, Merlin, OpenWrt, Pfsense, Synology, Tomato, Ubios: case DDWrt,
EdgeOS,
Firewalla,
Merlin,
OpenWrt,
Pfsense,
Synology,
Tomato,
Ubios:
if c.HasUpstreamSendClientInfo() { if c.HasUpstreamSendClientInfo() {
r := routerPlatform.Load() r := routerPlatform.Load()
r.sendClientInfo = true r.sendClientInfo = true
@@ -107,7 +135,7 @@ func ConfigureService(sc *service.Config) error {
sc.Option["SysvScript"] = openWrtScript sc.Option["SysvScript"] = openWrtScript
case Pfsense: case Pfsense:
sc.Option["SysvScript"] = pfsenseInitScript sc.Option["SysvScript"] = pfsenseInitScript
case EdgeOS, Merlin, Synology, Tomato, Ubios: case EdgeOS, Firewalla, Merlin, Synology, Tomato, Ubios:
} }
return nil return nil
} }
@@ -138,10 +166,12 @@ func PreRun() (err error) {
func PostInstall(svc *service.Config) error { func PostInstall(svc *service.Config) error {
name := Name() name := Name()
switch name { switch name {
case EdgeOS:
return postInstallEdgeOS()
case DDWrt: case DDWrt:
return postInstallDDWrt() return postInstallDDWrt()
case EdgeOS:
return postInstallEdgeOS()
case Firewalla:
return postInstallFirewalla()
case Merlin: case Merlin:
return postInstallMerlin() return postInstallMerlin()
case OpenWrt: case OpenWrt:
@@ -162,10 +192,12 @@ func PostInstall(svc *service.Config) error {
func Cleanup(svc *service.Config) error { func Cleanup(svc *service.Config) error {
name := Name() name := Name()
switch name { switch name {
case EdgeOS:
return cleanupEdgeOS()
case DDWrt: case DDWrt:
return cleanupDDWrt() return cleanupDDWrt()
case EdgeOS:
return cleanupEdgeOS()
case Firewalla:
return cleanupFirewalla()
case Merlin: case Merlin:
return cleanupMerlin() return cleanupMerlin()
case OpenWrt: case OpenWrt:
@@ -186,7 +218,7 @@ func Cleanup(svc *service.Config) error {
func ListenAddress() string { func ListenAddress() string {
name := Name() name := Name()
switch name { switch name {
case EdgeOS, DDWrt, Merlin, OpenWrt, Synology, Tomato, Ubios: case DDWrt, Firewalla, Merlin, OpenWrt, Synology, Tomato, Ubios:
return "127.0.0.1:5354" return "127.0.0.1:5354"
case Pfsense: case Pfsense:
// On pfsense, we run ctrld as DNS resolver. // On pfsense, we run ctrld as DNS resolver.
@@ -227,6 +259,8 @@ func distroName() string {
return EdgeOS // For 2.x return EdgeOS // For 2.x
case isPfsense(): case isPfsense():
return Pfsense return Pfsense
case haveFile("/etc/firewalla_release"):
return Firewalla
} }
return "" return ""
} }