Merge : *(home): do not require root privileges on the first run
* commit '7b2cc51e35bfb725f02e91cb991ddd099b81ee0c': fix function comment *(home): do not require root privileges on the first run
This commit is contained in:
commit
7d93457154
63
home/home.go
63
home/home.go
|
@ -1,23 +1,19 @@
|
||||||
package home
|
package home
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
@ -172,7 +168,7 @@ func run(args options) {
|
||||||
Context.firstRun = detectFirstRun()
|
Context.firstRun = detectFirstRun()
|
||||||
if Context.firstRun {
|
if Context.firstRun {
|
||||||
log.Info("This is the first time AdGuard Home is launched")
|
log.Info("This is the first time AdGuard Home is launched")
|
||||||
requireAdminRights()
|
checkPermissions()
|
||||||
}
|
}
|
||||||
|
|
||||||
initConfig()
|
initConfig()
|
||||||
|
@ -332,9 +328,13 @@ func StartMods() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the current user has root (administrator) rights
|
// Check if the current user permissions are enough to run AdGuard Home
|
||||||
// and if not, ask and try to run as root
|
func checkPermissions() {
|
||||||
func requireAdminRights() {
|
log.Info("Checking if AdGuard Home has necessary permissions")
|
||||||
|
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
// On Windows we need to have admin rights to run properly
|
||||||
|
|
||||||
admin, _ := util.HaveAdminRights()
|
admin, _ := util.HaveAdminRights()
|
||||||
if //noinspection ALL
|
if //noinspection ALL
|
||||||
admin || isdelve.Enabled {
|
admin || isdelve.Enabled {
|
||||||
|
@ -343,27 +343,40 @@ func requireAdminRights() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
log.Fatal("This is the first launch of AdGuard Home. You must run it as Administrator.")
|
log.Fatal("This is the first launch of AdGuard Home. You must run it as Administrator.")
|
||||||
|
|
||||||
} else {
|
|
||||||
log.Error("This is the first launch of AdGuard Home. You must run it as root.")
|
|
||||||
|
|
||||||
_, _ = io.WriteString(os.Stdout, "Do you want to start AdGuard Home as root user? [y/n] ")
|
|
||||||
stdin := bufio.NewReader(os.Stdin)
|
|
||||||
buf, _ := stdin.ReadString('\n')
|
|
||||||
buf = strings.TrimSpace(buf)
|
|
||||||
if buf != "y" {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command("sudo", os.Args...)
|
// We should check if AdGuard Home is able to bind to port 53
|
||||||
cmd.Stdin = os.Stdin
|
ok, err := util.CanBindPort(53)
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
if ok {
|
||||||
_ = cmd.Run()
|
log.Info("AdGuard Home can bind to port 53")
|
||||||
os.Exit(1)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opErr, ok := err.(*net.OpError); ok {
|
||||||
|
if sysErr, ok := opErr.Err.(*os.SyscallError); ok {
|
||||||
|
if errno, ok := sysErr.Err.(syscall.Errno); ok && errno == syscall.EACCES {
|
||||||
|
msg := `Permission check failed.
|
||||||
|
|
||||||
|
AdGuard Home is not allowed to bind to privileged ports (for instance, port 53).
|
||||||
|
Please note, that this is crucial for a server to be able to use privileged ports.
|
||||||
|
|
||||||
|
You have two options:
|
||||||
|
1. Run AdGuard Home with root privileges
|
||||||
|
2. On Linux you can grant the CAP_NET_BIND_SERVICE capability:
|
||||||
|
https://github.com/AdguardTeam/AdGuardHome/wiki/Getting-Started#running-without-superuser`
|
||||||
|
|
||||||
|
log.Fatal(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := fmt.Sprintf(`AdGuard failed to bind to port 53 due to %v
|
||||||
|
|
||||||
|
Please note, that this is crucial for a DNS server to be able to use that port.`, err)
|
||||||
|
|
||||||
|
log.Info(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write PID to a file
|
// Write PID to a file
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CanBindPort - checks if we can bind to this port or not
|
||||||
|
func CanBindPort(port int) (bool, error) {
|
||||||
|
addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("127.0.0.1:%d", port))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := net.ListenTCP("tcp", addr)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
_ = l.Close()
|
||||||
|
return true, nil
|
||||||
|
}
|
Loading…
Reference in New Issue