all: add firewalla support

This commit is contained in:
Cuong Manh Le
2023-06-21 00:28:33 +07:00
committed by Cuong Manh Le
parent 03781d4cec
commit 350d8355b1
5 changed files with 188 additions and 38 deletions

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.
var clientInfoFiles = map[string]readClientInfoFunc{
"/tmp/dnsmasq.leases": dnsmasqReadClientInfoFile, // ddwrt
"/tmp/dhcp.leases": dnsmasqReadClientInfoFile, // openwrt
"/var/lib/misc/dnsmasq.leases": dnsmasqReadClientInfoFile, // merlin
"/mnt/data/udapi-config/dnsmasq.lease": dnsmasqReadClientInfoFile, // UDM Pro
"/data/udapi-config/dnsmasq.lease": dnsmasqReadClientInfoFile, // UDR
"/etc/dhcpd/dhcpd-leases.log": dnsmasqReadClientInfoFile, // Synology
"/tmp/var/lib/misc/dnsmasq.leases": dnsmasqReadClientInfoFile, // Tomato
"/run/dnsmasq-dhcp.leases": dnsmasqReadClientInfoFile, // EdgeOS
"/run/dhcpd.leases": iscDHCPReadClientInfoFile, // EdgeOS
"/var/dhcpd/var/db/dhcpd.leases": iscDHCPReadClientInfoFile, // Pfsense
"/tmp/dnsmasq.leases": dnsmasqReadClientInfoFile, // ddwrt
"/tmp/dhcp.leases": dnsmasqReadClientInfoFile, // openwrt
"/var/lib/misc/dnsmasq.leases": dnsmasqReadClientInfoFile, // merlin
"/mnt/data/udapi-config/dnsmasq.lease": dnsmasqReadClientInfoFile, // UDM Pro
"/data/udapi-config/dnsmasq.lease": dnsmasqReadClientInfoFile, // UDR
"/etc/dhcpd/dhcpd-leases.log": dnsmasqReadClientInfoFile, // Synology
"/tmp/var/lib/misc/dnsmasq.leases": dnsmasqReadClientInfoFile, // Tomato
"/run/dnsmasq-dhcp.leases": dnsmasqReadClientInfoFile, // EdgeOS
"/run/dhcpd.leases": iscDHCPReadClientInfoFile, // EdgeOS
"/var/dhcpd/var/db/dhcpd.leases": iscDHCPReadClientInfoFile, // Pfsense
"/home/pi/.router/run/dhcp/dnsmasq.leases": dnsmasqReadClientInfoFile, // Firewalla
}
// watchClientInfoTable watches changes happens in dnsmasq/dhcpd

View File

@@ -1,6 +1,7 @@
package router
import (
"fmt"
"strings"
"text/template"
)
@@ -49,8 +50,10 @@ func dnsMasqConf() (string, error) {
var sb strings.Builder
var tmplText string
switch Name() {
case EdgeOS, DDWrt, OpenWrt, Ubios, Synology, Tomato:
case DDWrt, EdgeOS, OpenWrt, Ubios, Synology, Tomato:
tmplText = dnsMasqConfigContentTmpl
case Firewalla:
tmplText = dnsMasqConfigContentTmpl + fmt.Sprintf("listen-address=127.0.0.1\n")
case Merlin:
tmplText = merlinDNSMasqPostConfTmpl
}
@@ -68,10 +71,12 @@ func dnsMasqConf() (string, error) {
func restartDNSMasq() error {
switch Name() {
case EdgeOS:
return edgeOSRestartDNSMasq()
case DDWrt:
return ddwrtRestartDNSMasq()
case EdgeOS:
return edgeOSRestartDNSMasq()
case Firewalla:
return firewallaRestartDNSMasq()
case Merlin:
return merlinRestartDNSMasq()
case OpenWrt:

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)
}

View File

@@ -19,14 +19,15 @@ import (
)
const (
OpenWrt = "openwrt"
DDWrt = "ddwrt"
Merlin = "merlin"
Ubios = "ubios"
Synology = "synology"
Tomato = "tomato"
EdgeOS = "edgeos"
Pfsense = "pfsense"
DDWrt = "ddwrt"
EdgeOS = "edgeos"
Firewalla = "firewalla"
Merlin = "merlin"
OpenWrt = "openwrt"
Pfsense = "pfsense"
Synology = "synology"
Tomato = "tomato"
Ubios = "ubios"
)
// 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.
func IsSupported(platform string) bool {
switch platform {
case EdgeOS, DDWrt, Merlin, OpenWrt, Pfsense, Synology, Tomato, Ubios:
case DDWrt,
EdgeOS,
Firewalla,
Merlin,
OpenWrt,
Pfsense,
Synology,
Tomato,
Ubios:
return true
}
return false
@@ -52,25 +61,44 @@ func IsSupported(platform string) bool {
// SupportedPlatforms return all platforms that can be configured to run with ctrld.
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{
EdgeOS: setupEdgeOS,
DDWrt: setupDDWrt,
Merlin: setupMerlin,
OpenWrt: setupOpenWrt,
Pfsense: setupPfsense,
Synology: setupSynology,
Tomato: setupTomato,
Ubios: setupUbiOS,
DDWrt: setupDDWrt,
EdgeOS: setupEdgeOS,
Firewalla: setupFirewalla,
Merlin: setupMerlin,
OpenWrt: setupOpenWrt,
Pfsense: setupPfsense,
Synology: setupSynology,
Tomato: setupTomato,
Ubios: setupUbiOS,
}
// Configure configures things for running ctrld on the router.
func Configure(c *ctrld.Config) error {
name := 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() {
r := routerPlatform.Load()
r.sendClientInfo = true
@@ -107,7 +135,7 @@ func ConfigureService(sc *service.Config) error {
sc.Option["SysvScript"] = openWrtScript
case Pfsense:
sc.Option["SysvScript"] = pfsenseInitScript
case EdgeOS, Merlin, Synology, Tomato, Ubios:
case EdgeOS, Firewalla, Merlin, Synology, Tomato, Ubios:
}
return nil
}
@@ -138,10 +166,12 @@ func PreRun() (err error) {
func PostInstall(svc *service.Config) error {
name := Name()
switch name {
case EdgeOS:
return postInstallEdgeOS()
case DDWrt:
return postInstallDDWrt()
case EdgeOS:
return postInstallEdgeOS()
case Firewalla:
return postInstallFirewalla()
case Merlin:
return postInstallMerlin()
case OpenWrt:
@@ -162,10 +192,12 @@ func PostInstall(svc *service.Config) error {
func Cleanup(svc *service.Config) error {
name := Name()
switch name {
case EdgeOS:
return cleanupEdgeOS()
case DDWrt:
return cleanupDDWrt()
case EdgeOS:
return cleanupEdgeOS()
case Firewalla:
return cleanupFirewalla()
case Merlin:
return cleanupMerlin()
case OpenWrt:
@@ -186,7 +218,7 @@ func Cleanup(svc *service.Config) error {
func ListenAddress() string {
name := 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"
case Pfsense:
// On pfsense, we run ctrld as DNS resolver.
@@ -227,6 +259,8 @@ func distroName() string {
return EdgeOS // For 2.x
case isPfsense():
return Pfsense
case haveFile("/etc/firewalla_release"):
return Firewalla
}
return ""
}