mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2025-05-01 21:50:29 +03:00
Merge branch 'master' into 4990-custom-ciphers
This commit is contained in:
commit
a736f67205
109 changed files with 3936 additions and 2010 deletions
internal/home
|
@ -10,6 +10,7 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
@ -58,7 +59,7 @@ type homeContext struct {
|
|||
auth *Auth // HTTP authentication module
|
||||
filters *filtering.DNSFilter // DNS filtering module
|
||||
web *Web // Web (HTTP, HTTPS) module
|
||||
tls *TLSMod // TLS module
|
||||
tls *tlsManager // TLS module
|
||||
// etcHosts is an IP-hostname pairs set taken from system configuration
|
||||
// (e.g. /etc/hosts) files.
|
||||
etcHosts *aghnet.HostsContainer
|
||||
|
@ -97,9 +98,15 @@ var Context homeContext
|
|||
|
||||
// Main is the entry point
|
||||
func Main(clientBuildFS fs.FS) {
|
||||
// config can be specified, which reads options from there, but other command line flags have to override config values
|
||||
// therefore, we must do it manually instead of using a lib
|
||||
args := loadOptions()
|
||||
initCmdLineOpts()
|
||||
|
||||
// The configuration file path can be overridden, but other command-line
|
||||
// options have to override config values. Therefore, do it manually
|
||||
// instead of using package flag.
|
||||
//
|
||||
// TODO(a.garipov): The comment above is most likely false. Replace with
|
||||
// package flag.
|
||||
opts := loadCmdLineOpts()
|
||||
|
||||
Context.appSignalChannel = make(chan os.Signal)
|
||||
signal.Notify(Context.appSignalChannel, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
|
||||
|
@ -110,7 +117,7 @@ func Main(clientBuildFS fs.FS) {
|
|||
switch sig {
|
||||
case syscall.SIGHUP:
|
||||
Context.clients.Reload()
|
||||
Context.tls.Reload()
|
||||
Context.tls.reload()
|
||||
|
||||
default:
|
||||
cleanup(context.Background())
|
||||
|
@ -120,26 +127,18 @@ func Main(clientBuildFS fs.FS) {
|
|||
}
|
||||
}()
|
||||
|
||||
if args.serviceControlAction != "" {
|
||||
handleServiceControlAction(args, clientBuildFS)
|
||||
if opts.serviceControlAction != "" {
|
||||
handleServiceControlAction(opts, clientBuildFS)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// run the protection
|
||||
run(args, clientBuildFS)
|
||||
run(opts, clientBuildFS)
|
||||
}
|
||||
|
||||
func setupContext(args options) {
|
||||
Context.runningAsService = args.runningAsService
|
||||
Context.disableUpdate = args.disableUpdate ||
|
||||
version.Channel() == version.ChannelDevelopment
|
||||
|
||||
Context.firstRun = detectFirstRun()
|
||||
if Context.firstRun {
|
||||
log.Info("This is the first time AdGuard Home is launched")
|
||||
checkPermissions()
|
||||
}
|
||||
func setupContext(opts options) {
|
||||
setupContextFlags(opts)
|
||||
|
||||
switch version.Channel() {
|
||||
case version.ChannelEdge, version.ChannelDevelopment:
|
||||
|
@ -148,7 +147,7 @@ func setupContext(args options) {
|
|||
// Go on.
|
||||
}
|
||||
|
||||
Context.tlsRoots = LoadSystemRootCAs()
|
||||
Context.tlsRoots = aghtls.SystemRootCAs()
|
||||
Context.transport = &http.Transport{
|
||||
DialContext: customDialContext,
|
||||
Proxy: getHTTPProxy,
|
||||
|
@ -174,13 +173,13 @@ func setupContext(args options) {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
if args.checkConfig {
|
||||
if opts.checkConfig {
|
||||
log.Info("configuration file is ok")
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if !args.noEtcHosts && config.Clients.Sources.HostsFile {
|
||||
if !opts.noEtcHosts && config.Clients.Sources.HostsFile {
|
||||
err = setupHostsContainer()
|
||||
fatalOnError(err)
|
||||
}
|
||||
|
@ -189,6 +188,24 @@ func setupContext(args options) {
|
|||
Context.mux = http.NewServeMux()
|
||||
}
|
||||
|
||||
// setupContextFlags sets global flags and prints their status to the log.
|
||||
func setupContextFlags(opts options) {
|
||||
Context.firstRun = detectFirstRun()
|
||||
if Context.firstRun {
|
||||
log.Info("This is the first time AdGuard Home is launched")
|
||||
checkPermissions()
|
||||
}
|
||||
|
||||
Context.runningAsService = opts.runningAsService
|
||||
// Don't print the runningAsService flag, since that has already been done
|
||||
// in [run].
|
||||
|
||||
Context.disableUpdate = opts.disableUpdate || version.Channel() == version.ChannelDevelopment
|
||||
if Context.disableUpdate {
|
||||
log.Info("AdGuard Home updates are disabled")
|
||||
}
|
||||
}
|
||||
|
||||
// logIfUnsupported logs a formatted warning if the error is one of the
|
||||
// unsupported errors and returns nil. If err is nil, logIfUnsupported returns
|
||||
// nil. Otherwise, it returns err.
|
||||
|
@ -270,7 +287,7 @@ func setupHostsContainer() (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func setupConfig(args options) (err error) {
|
||||
func setupConfig(opts options) (err error) {
|
||||
config.DNS.DnsfilterConf.EtcHosts = Context.etcHosts
|
||||
config.DNS.DnsfilterConf.ConfigModified = onConfigModified
|
||||
config.DNS.DnsfilterConf.HTTPRegister = httpRegister
|
||||
|
@ -312,9 +329,9 @@ func setupConfig(args options) (err error) {
|
|||
|
||||
Context.clients.Init(config.Clients.Persistent, Context.dhcpServer, Context.etcHosts, arpdb)
|
||||
|
||||
if args.bindPort != 0 {
|
||||
if opts.bindPort != 0 {
|
||||
tcpPorts := aghalg.UniqChecker[tcpPort]{}
|
||||
addPorts(tcpPorts, tcpPort(args.bindPort), tcpPort(config.BetaBindPort))
|
||||
addPorts(tcpPorts, tcpPort(opts.bindPort), tcpPort(config.BetaBindPort))
|
||||
|
||||
udpPorts := aghalg.UniqChecker[udpPort]{}
|
||||
addPorts(udpPorts, udpPort(config.DNS.Port))
|
||||
|
@ -336,23 +353,23 @@ func setupConfig(args options) (err error) {
|
|||
return fmt.Errorf("validating udp ports: %w", err)
|
||||
}
|
||||
|
||||
config.BindPort = args.bindPort
|
||||
config.BindPort = opts.bindPort
|
||||
}
|
||||
|
||||
// override bind host/port from the console
|
||||
if args.bindHost != nil {
|
||||
config.BindHost = args.bindHost
|
||||
if opts.bindHost.IsValid() {
|
||||
config.BindHost = opts.bindHost
|
||||
}
|
||||
if len(args.pidFile) != 0 && writePIDFile(args.pidFile) {
|
||||
Context.pidFileName = args.pidFile
|
||||
if len(opts.pidFile) != 0 && writePIDFile(opts.pidFile) {
|
||||
Context.pidFileName = opts.pidFile
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initWeb(args options, clientBuildFS fs.FS) (web *Web, err error) {
|
||||
func initWeb(opts options, clientBuildFS fs.FS) (web *Web, err error) {
|
||||
var clientFS, clientBetaFS fs.FS
|
||||
if args.localFrontend {
|
||||
if opts.localFrontend {
|
||||
log.Info("warning: using local frontend files")
|
||||
|
||||
clientFS = os.DirFS("build/static")
|
||||
|
@ -406,24 +423,24 @@ func fatalOnError(err error) {
|
|||
}
|
||||
|
||||
// run configures and starts AdGuard Home.
|
||||
func run(args options, clientBuildFS fs.FS) {
|
||||
func run(opts options, clientBuildFS fs.FS) {
|
||||
// configure config filename
|
||||
initConfigFilename(args)
|
||||
initConfigFilename(opts)
|
||||
|
||||
// configure working dir and config path
|
||||
initWorkingDir(args)
|
||||
initWorkingDir(opts)
|
||||
|
||||
// configure log level and output
|
||||
configureLogger(args)
|
||||
configureLogger(opts)
|
||||
|
||||
// Print the first message after logger is configured.
|
||||
log.Info(version.Full())
|
||||
log.Debug("current working directory is %s", Context.workDir)
|
||||
if args.runningAsService {
|
||||
if opts.runningAsService {
|
||||
log.Info("AdGuard Home is running as a service")
|
||||
}
|
||||
|
||||
setupContext(args)
|
||||
setupContext(opts)
|
||||
|
||||
err := configureOS(config)
|
||||
fatalOnError(err)
|
||||
|
@ -433,7 +450,7 @@ func run(args options, clientBuildFS fs.FS) {
|
|||
// but also avoid relying on automatic Go init() function
|
||||
filtering.InitModule()
|
||||
|
||||
err = setupConfig(args)
|
||||
err = setupConfig(opts)
|
||||
fatalOnError(err)
|
||||
|
||||
if !Context.firstRun {
|
||||
|
@ -462,7 +479,7 @@ func run(args options, clientBuildFS fs.FS) {
|
|||
}
|
||||
|
||||
sessFilename := filepath.Join(Context.getDataDir(), "sessions.db")
|
||||
GLMode = args.glinetMode
|
||||
GLMode = opts.glinetMode
|
||||
var rateLimiter *authRateLimiter
|
||||
if config.AuthAttempts > 0 && config.AuthBlockMin > 0 {
|
||||
rateLimiter = newAuthRateLimiter(
|
||||
|
@ -484,19 +501,19 @@ func run(args options, clientBuildFS fs.FS) {
|
|||
}
|
||||
config.Users = nil
|
||||
|
||||
Context.tls = tlsCreate(config.TLS)
|
||||
if Context.tls == nil {
|
||||
log.Fatalf("Can't initialize TLS module")
|
||||
Context.tls, err = newTLSManager(config.TLS)
|
||||
if err != nil {
|
||||
log.Fatalf("initializing tls: %s", err)
|
||||
}
|
||||
|
||||
Context.web, err = initWeb(args, clientBuildFS)
|
||||
Context.web, err = initWeb(opts, clientBuildFS)
|
||||
fatalOnError(err)
|
||||
|
||||
if !Context.firstRun {
|
||||
err = initDNSServer()
|
||||
fatalOnError(err)
|
||||
|
||||
Context.tls.Start()
|
||||
Context.tls.start()
|
||||
|
||||
go func() {
|
||||
serr := startDNSServer()
|
||||
|
@ -520,20 +537,22 @@ func run(args options, clientBuildFS fs.FS) {
|
|||
select {}
|
||||
}
|
||||
|
||||
// StartMods initializes and starts the DNS server after installation.
|
||||
func StartMods() error {
|
||||
// startMods initializes and starts the DNS server after installation.
|
||||
func startMods() error {
|
||||
err := initDNSServer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Context.tls.Start()
|
||||
Context.tls.start()
|
||||
|
||||
err = startDNSServer()
|
||||
if err != nil {
|
||||
closeDNSServer()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -546,7 +565,7 @@ func checkPermissions() {
|
|||
}
|
||||
|
||||
// We should check if AdGuard Home is able to bind to port 53
|
||||
err := aghnet.CheckPort("tcp", net.IP{127, 0, 0, 1}, defaultPortDNS)
|
||||
err := aghnet.CheckPort("tcp", netip.AddrPortFrom(aghnet.IPv4Localhost(), defaultPortDNS))
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrPermission) {
|
||||
log.Fatal(`Permission check failed.
|
||||
|
@ -581,10 +600,10 @@ func writePIDFile(fn string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func initConfigFilename(args options) {
|
||||
func initConfigFilename(opts options) {
|
||||
// config file path can be overridden by command-line arguments:
|
||||
if args.configFilename != "" {
|
||||
Context.configFilename = args.configFilename
|
||||
if opts.confFilename != "" {
|
||||
Context.configFilename = opts.confFilename
|
||||
} else {
|
||||
// Default config file name
|
||||
Context.configFilename = "AdGuardHome.yaml"
|
||||
|
@ -593,15 +612,15 @@ func initConfigFilename(args options) {
|
|||
|
||||
// initWorkingDir initializes the workDir
|
||||
// if no command-line arguments specified, we use the directory where our binary file is located
|
||||
func initWorkingDir(args options) {
|
||||
func initWorkingDir(opts options) {
|
||||
execPath, err := os.Executable()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if args.workDir != "" {
|
||||
if opts.workDir != "" {
|
||||
// If there is a custom config file, use it's directory as our working dir
|
||||
Context.workDir = args.workDir
|
||||
Context.workDir = opts.workDir
|
||||
} else {
|
||||
Context.workDir = filepath.Dir(execPath)
|
||||
}
|
||||
|
@ -615,15 +634,15 @@ func initWorkingDir(args options) {
|
|||
}
|
||||
|
||||
// configureLogger configures logger level and output
|
||||
func configureLogger(args options) {
|
||||
func configureLogger(opts options) {
|
||||
ls := getLogSettings()
|
||||
|
||||
// command-line arguments can override config settings
|
||||
if args.verbose || config.Verbose {
|
||||
if opts.verbose || config.Verbose {
|
||||
ls.Verbose = true
|
||||
}
|
||||
if args.logFile != "" {
|
||||
ls.File = args.logFile
|
||||
if opts.logFile != "" {
|
||||
ls.File = opts.logFile
|
||||
} else if config.File != "" {
|
||||
ls.File = config.File
|
||||
}
|
||||
|
@ -644,7 +663,7 @@ func configureLogger(args options) {
|
|||
// happen pretty quickly.
|
||||
log.SetFlags(log.LstdFlags | log.Lmicroseconds)
|
||||
|
||||
if args.runningAsService && ls.File == "" && runtime.GOOS == "windows" {
|
||||
if opts.runningAsService && ls.File == "" && runtime.GOOS == "windows" {
|
||||
// When running as a Windows service, use eventlog by default if nothing
|
||||
// else is configured. Otherwise, we'll simply lose the log output.
|
||||
ls.File = configSyslog
|
||||
|
@ -717,7 +736,6 @@ func cleanup(ctx context.Context) {
|
|||
}
|
||||
|
||||
if Context.tls != nil {
|
||||
Context.tls.Close()
|
||||
Context.tls = nil
|
||||
}
|
||||
}
|
||||
|
@ -727,32 +745,37 @@ func cleanupAlways() {
|
|||
if len(Context.pidFileName) != 0 {
|
||||
_ = os.Remove(Context.pidFileName)
|
||||
}
|
||||
log.Info("Stopped")
|
||||
|
||||
log.Info("stopped")
|
||||
}
|
||||
|
||||
func exitWithError() {
|
||||
os.Exit(64)
|
||||
}
|
||||
|
||||
// loadOptions reads command line arguments and initializes configuration
|
||||
func loadOptions() options {
|
||||
o, f, err := parse(os.Args[0], os.Args[1:])
|
||||
|
||||
// loadCmdLineOpts reads command line arguments and initializes configuration
|
||||
// from them. If there is an error or an effect, loadCmdLineOpts processes them
|
||||
// and exits.
|
||||
func loadCmdLineOpts() (opts options) {
|
||||
opts, eff, err := parseCmdOpts(os.Args[0], os.Args[1:])
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
_ = printHelp(os.Args[0])
|
||||
printHelp(os.Args[0])
|
||||
|
||||
exitWithError()
|
||||
} else if f != nil {
|
||||
err = f()
|
||||
}
|
||||
|
||||
if eff != nil {
|
||||
err = eff()
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
exitWithError()
|
||||
} else {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
return o
|
||||
return opts
|
||||
}
|
||||
|
||||
// printWebAddrs prints addresses built from proto, addr, and an appropriate
|
||||
|
@ -901,6 +924,6 @@ func getTLSCiphers() (cipherIds []uint16, err error) {
|
|||
return aghtls.SaferCipherSuites(), nil
|
||||
} else {
|
||||
log.Info("Overriding TLS Ciphers : %s", config.TLS.OverrideTLSCiphers)
|
||||
return aghtls.ParseCipherIDs(config.TLS.OverrideTLSCiphers)
|
||||
return aghtls.ParseCiphers(config.TLS.OverrideTLSCiphers)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue