mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-08-10 13:20:33 +02:00
all: add firewalla support
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
@@ -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 ""
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user