2018-01-09 00:24:51 +01:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2019-06-03 16:44:09 +02:00
|
|
|
crypto_rand "crypto/rand"
|
|
|
|
"encoding/binary"
|
2018-01-17 11:28:43 +01:00
|
|
|
"flag"
|
|
|
|
"fmt"
|
2019-06-03 16:44:09 +02:00
|
|
|
"math/rand"
|
2018-02-28 18:11:48 +01:00
|
|
|
"os"
|
2020-06-09 09:41:58 +02:00
|
|
|
"runtime"
|
2019-10-31 17:36:59 +01:00
|
|
|
"sync"
|
2018-01-09 00:24:51 +01:00
|
|
|
|
2018-01-11 11:50:54 +01:00
|
|
|
"github.com/jedisct1/dlog"
|
2018-01-17 11:28:43 +01:00
|
|
|
"github.com/kardianos/service"
|
2018-01-09 00:24:51 +01:00
|
|
|
)
|
|
|
|
|
2018-01-29 23:57:20 +01:00
|
|
|
const (
|
2023-08-11 18:56:31 +02:00
|
|
|
AppVersion = "2.1.5"
|
2018-01-31 08:38:22 +01:00
|
|
|
DefaultConfigFileName = "dnscrypt-proxy.toml"
|
2018-01-29 23:57:20 +01:00
|
|
|
)
|
2018-01-18 12:22:25 +01:00
|
|
|
|
2018-01-17 10:58:19 +01:00
|
|
|
type App struct {
|
2019-10-31 17:36:59 +01:00
|
|
|
wg sync.WaitGroup
|
|
|
|
quit chan struct{}
|
2019-10-09 17:59:46 +02:00
|
|
|
proxy *Proxy
|
2019-10-30 14:34:00 +01:00
|
|
|
flags *ConfigFlags
|
2018-01-17 10:58:19 +01:00
|
|
|
}
|
|
|
|
|
2018-01-09 13:35:10 +01:00
|
|
|
func main() {
|
2023-06-24 22:23:12 +02:00
|
|
|
tzErr := TimezoneSetup()
|
2018-01-18 14:25:45 +01:00
|
|
|
dlog.Init("dnscrypt-proxy", dlog.SeverityNotice, "DAEMON")
|
2023-06-24 22:23:12 +02:00
|
|
|
if tzErr != nil {
|
2023-06-24 22:23:30 +02:00
|
|
|
dlog.Warnf("Timezone setup failed: [%v]", tzErr)
|
2023-06-24 22:23:12 +02:00
|
|
|
}
|
2021-03-08 15:36:30 +01:00
|
|
|
runtime.MemProfileRate = 0
|
2018-04-03 19:42:27 +02:00
|
|
|
|
2019-06-03 16:44:09 +02:00
|
|
|
seed := make([]byte, 8)
|
2023-06-06 09:16:44 +02:00
|
|
|
if _, err := crypto_rand.Read(seed); err != nil {
|
|
|
|
dlog.Fatal(err)
|
|
|
|
}
|
2023-06-24 21:56:03 +02:00
|
|
|
rand.Seed(int64(binary.LittleEndian.Uint64(seed)))
|
2019-06-03 16:44:09 +02:00
|
|
|
|
2018-04-03 20:15:33 +02:00
|
|
|
pwd, err := os.Getwd()
|
2018-04-03 19:42:27 +02:00
|
|
|
if err != nil {
|
2018-04-03 20:15:33 +02:00
|
|
|
dlog.Fatal("Unable to find the path to the current directory")
|
2018-04-03 19:42:27 +02:00
|
|
|
}
|
2019-12-23 15:33:57 +01:00
|
|
|
|
2018-01-17 11:28:43 +01:00
|
|
|
svcFlag := flag.String("service", "", fmt.Sprintf("Control the system service: %q", service.ControlAction))
|
2019-10-30 14:30:31 +01:00
|
|
|
version := flag.Bool("version", false, "print current proxy version")
|
|
|
|
flags := ConfigFlags{}
|
2021-01-02 22:20:52 +01:00
|
|
|
flags.Resolve = flag.String("resolve", "", "resolve a DNS name (string can be <name> or <name>,<resolver address>)")
|
2019-10-30 14:30:31 +01:00
|
|
|
flags.List = flag.Bool("list", false, "print the list of available resolvers for the enabled filters")
|
|
|
|
flags.ListAll = flag.Bool("list-all", false, "print the complete list of available resolvers, ignoring filters")
|
2019-12-11 14:08:48 +01:00
|
|
|
flags.JSONOutput = flag.Bool("json", false, "output list as JSON")
|
2019-10-30 14:30:31 +01:00
|
|
|
flags.Check = flag.Bool("check", false, "check the configuration file and exit")
|
|
|
|
flags.ConfigFile = flag.String("config", DefaultConfigFileName, "Path to the configuration file")
|
|
|
|
flags.Child = flag.Bool("child", false, "Invokes program as a child process")
|
|
|
|
flags.NetprobeTimeoutOverride = flag.Int("netprobe-timeout", 60, "Override the netprobe timeout")
|
|
|
|
flags.ShowCerts = flag.Bool("show-certs", false, "print DoH certificate chain hashes")
|
|
|
|
|
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
if *version {
|
|
|
|
fmt.Println(AppVersion)
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
|
2019-10-30 14:34:00 +01:00
|
|
|
app := &App{
|
|
|
|
flags: &flags,
|
|
|
|
}
|
2019-12-23 15:33:57 +01:00
|
|
|
|
|
|
|
svcConfig := &service.Config{
|
|
|
|
Name: "dnscrypt-proxy",
|
|
|
|
DisplayName: "DNSCrypt client proxy",
|
|
|
|
Description: "Encrypted/authenticated DNS proxy",
|
|
|
|
WorkingDirectory: pwd,
|
2019-12-23 15:35:52 +01:00
|
|
|
Arguments: []string{"-config", *flags.ConfigFile},
|
2019-12-23 15:33:57 +01:00
|
|
|
}
|
2018-01-17 11:28:43 +01:00
|
|
|
svc, err := service.New(app, svcConfig)
|
|
|
|
if err != nil {
|
2018-01-18 02:07:31 +01:00
|
|
|
svc = nil
|
|
|
|
dlog.Debug(err)
|
2018-01-17 10:58:19 +01:00
|
|
|
}
|
2019-12-23 15:33:57 +01:00
|
|
|
|
2018-02-04 21:13:54 +01:00
|
|
|
app.proxy = NewProxy()
|
2018-07-19 19:03:57 +02:00
|
|
|
_ = ServiceManagerStartNotify()
|
2018-01-17 11:28:43 +01:00
|
|
|
if len(*svcFlag) != 0 {
|
2018-02-20 00:34:06 +01:00
|
|
|
if svc == nil {
|
|
|
|
dlog.Fatal("Built-in service installation is not supported on this platform")
|
|
|
|
}
|
2018-01-17 11:28:43 +01:00
|
|
|
if err := service.Control(svc, *svcFlag); err != nil {
|
|
|
|
dlog.Fatal(err)
|
|
|
|
}
|
|
|
|
if *svcFlag == "install" {
|
|
|
|
dlog.Notice("Installed as a service. Use `-service start` to start")
|
|
|
|
} else if *svcFlag == "uninstall" {
|
|
|
|
dlog.Notice("Service uninstalled")
|
|
|
|
} else if *svcFlag == "start" {
|
|
|
|
dlog.Notice("Service started")
|
|
|
|
} else if *svcFlag == "stop" {
|
|
|
|
dlog.Notice("Service stopped")
|
|
|
|
} else if *svcFlag == "restart" {
|
|
|
|
dlog.Notice("Service restarted")
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2018-01-18 02:07:31 +01:00
|
|
|
if svc != nil {
|
2020-03-13 18:44:30 +01:00
|
|
|
if err := svc.Run(); err != nil {
|
2018-01-18 02:07:31 +01:00
|
|
|
dlog.Fatal(err)
|
|
|
|
}
|
|
|
|
} else {
|
2019-10-30 20:01:37 +01:00
|
|
|
app.Start(nil)
|
2018-01-10 12:01:49 +01:00
|
|
|
}
|
2018-01-17 11:28:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (app *App) Start(service service.Service) error {
|
2019-10-31 17:49:48 +01:00
|
|
|
if service != nil {
|
|
|
|
go func() {
|
|
|
|
app.AppMain()
|
|
|
|
}()
|
|
|
|
} else {
|
|
|
|
app.AppMain()
|
2018-01-18 02:07:31 +01:00
|
|
|
}
|
2018-01-17 10:58:19 +01:00
|
|
|
return nil
|
2018-01-09 00:24:51 +01:00
|
|
|
}
|
|
|
|
|
2019-10-31 17:49:48 +01:00
|
|
|
func (app *App) AppMain() {
|
2019-10-30 14:34:00 +01:00
|
|
|
if err := ConfigLoad(app.proxy, app.flags); err != nil {
|
|
|
|
dlog.Fatal(err)
|
|
|
|
}
|
2020-07-10 14:37:35 +02:00
|
|
|
if err := PidFileCreate(); err != nil {
|
2023-06-24 22:23:30 +02:00
|
|
|
dlog.Errorf("Unable to create the PID file: [%v]", err)
|
2020-07-10 14:37:35 +02:00
|
|
|
}
|
2019-10-30 14:34:00 +01:00
|
|
|
if err := app.proxy.InitPluginsGlobals(); err != nil {
|
|
|
|
dlog.Fatal(err)
|
|
|
|
}
|
|
|
|
app.quit = make(chan struct{})
|
|
|
|
app.wg.Add(1)
|
2019-10-31 17:49:48 +01:00
|
|
|
app.proxy.StartProxy()
|
2020-06-09 09:41:58 +02:00
|
|
|
runtime.GC()
|
2019-10-31 17:49:48 +01:00
|
|
|
<-app.quit
|
|
|
|
dlog.Notice("Quit signal received...")
|
2019-10-31 17:36:59 +01:00
|
|
|
app.wg.Done()
|
2018-01-18 02:07:31 +01:00
|
|
|
}
|
|
|
|
|
2019-10-31 17:49:48 +01:00
|
|
|
func (app *App) Stop(service service.Service) error {
|
2023-06-24 22:23:12 +02:00
|
|
|
if err := PidFileRemove(); err != nil {
|
2023-06-24 22:23:30 +02:00
|
|
|
dlog.Warnf("Failed to remove the PID file: [%v]", err)
|
2023-06-24 22:23:12 +02:00
|
|
|
}
|
2019-10-31 17:49:48 +01:00
|
|
|
dlog.Notice("Stopped.")
|
|
|
|
return nil
|
2018-01-14 00:56:46 +01:00
|
|
|
}
|