Back to 2.0.29 beta 3 (ceed905196)

This commit is contained in:
Frank Denis 2019-10-31 17:49:48 +01:00
parent fb1fc14317
commit 3a68f90c37
9 changed files with 118 additions and 172 deletions

View File

@ -194,17 +194,6 @@ type ServerSummary struct {
Stamp string `json:"stamp"`
}
type ConfigFlags struct {
List *bool
ListAll *bool
JsonOutput *bool
Check *bool
ConfigFile *string
Child *bool
NetprobeTimeoutOverride *int
ShowCerts *bool
}
func findConfigFile(configFile *string) (string, error) {
if _, err := os.Stat(*configFile); os.IsNotExist(err) {
cdLocal()
@ -222,10 +211,35 @@ func findConfigFile(configFile *string) (string, error) {
return path.Join(pwd, *configFile), nil
}
func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
foundConfigFile, err := findConfigFile(flags.ConfigFile)
func ConfigLoad(proxy *Proxy, svcFlag *string) error {
version := flag.Bool("version", false, "print current proxy version")
resolve := flag.String("resolve", "", "resolve a name using system libraries")
list := flag.Bool("list", false, "print the list of available resolvers for the enabled filters")
listAll := flag.Bool("list-all", false, "print the complete list of available resolvers, ignoring filters")
jsonOutput := flag.Bool("json", false, "output list as JSON")
check := flag.Bool("check", false, "check the configuration file and exit")
configFile := flag.String("config", DefaultConfigFileName, "Path to the configuration file")
child := flag.Bool("child", false, "Invokes program as a child process")
netprobeTimeoutOverride := flag.Int("netprobe-timeout", 60, "Override the netprobe timeout")
showCerts := flag.Bool("show-certs", false, "print DoH certificate chain hashes")
flag.Parse()
if *svcFlag == "stop" || *svcFlag == "uninstall" {
return nil
}
if *version {
fmt.Println(AppVersion)
os.Exit(0)
}
if resolve != nil && len(*resolve) > 0 {
Resolve(*resolve)
os.Exit(0)
}
foundConfigFile, err := findConfigFile(configFile)
if err != nil {
dlog.Fatalf("Unable to load the configuration file [%s] -- Maybe use the -config command-line switch?", *flags.ConfigFile)
dlog.Fatalf("Unable to load the configuration file [%s] -- Maybe use the -config command-line switch?", *configFile)
}
config := newConfig()
md, err := toml.DecodeFile(foundConfigFile, &config)
@ -247,7 +261,7 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
dlog.UseSyslog(true)
} else if config.LogFile != nil {
dlog.UseLogFile(*config.LogFile)
if !*flags.Child {
if !*child {
FileDescriptors = append(FileDescriptors, dlog.GetFileDescriptor())
} else {
FileDescriptorNum++
@ -260,7 +274,7 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
proxy.userName = config.UserName
proxy.child = *flags.Child
proxy.child = *child
proxy.xTransport = NewXTransport()
proxy.xTransport.tlsDisableSessionTickets = config.TLSDisableSessionTickets
proxy.xTransport.tlsCipherSuite = config.TLSCipherSuite
@ -437,7 +451,7 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
proxy.routes = &routes
}
if *flags.ListAll {
if *listAll {
config.ServerNames = nil
config.DisabledServerNames = nil
config.SourceRequireDNSSEC = false
@ -451,8 +465,8 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
netprobeTimeout := config.NetprobeTimeout
flag.Visit(func(flag *flag.Flag) {
if flag.Name == "netprobe-timeout" && flags.NetprobeTimeoutOverride != nil {
netprobeTimeout = *flags.NetprobeTimeoutOverride
if flag.Name == "netprobe-timeout" && netprobeTimeoutOverride != nil {
netprobeTimeout = *netprobeTimeoutOverride
}
})
netprobeAddress := DefaultNetprobeAddress
@ -461,9 +475,9 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
} else if len(config.FallbackResolver) > 0 {
netprobeAddress = config.FallbackResolver
}
proxy.showCerts = *flags.ShowCerts || len(os.Getenv("SHOW_CERTS")) > 0
proxy.showCerts = *showCerts || len(os.Getenv("SHOW_CERTS")) > 0
if proxy.showCerts {
proxy.listenAddresses = proxy.listenAddresses[0:0]
proxy.listenAddresses = nil
}
dlog.Noticef("dnscrypt-proxy %s", AppVersion)
if err := NetProbe(netprobeAddress, netprobeTimeout); err != nil {
@ -477,8 +491,8 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
return errors.New("No servers configured")
}
}
if *flags.List || *flags.ListAll {
config.printRegisteredServers(proxy, *flags.JsonOutput)
if *list || *listAll {
config.printRegisteredServers(proxy, *jsonOutput)
os.Exit(0)
}
if proxy.routes != nil && len(*proxy.routes) > 0 {
@ -501,7 +515,7 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
}
}
}
if *flags.Check {
if *check {
dlog.Notice("Configuration successfully checked")
os.Exit(0)
}
@ -614,11 +628,11 @@ func (config *Config) loadSource(proxy *Proxy, requiredProps stamps.ServerInform
cfgSource.RefreshDelay = 72
}
source, sourceUrlsToPrefetch, err := NewSource(proxy.xTransport, cfgSource.URLs, cfgSource.MinisignKeyStr, cfgSource.CacheFile, cfgSource.FormatStr, time.Duration(cfgSource.RefreshDelay)*time.Hour)
proxy.urlsToPrefetch = append(proxy.urlsToPrefetch, sourceUrlsToPrefetch...)
if err != nil {
dlog.Criticalf("Unable to retrieve source [%s]: [%s]", cfgSourceName, err)
return err
}
proxy.urlsToPrefetch = append(proxy.urlsToPrefetch, sourceUrlsToPrefetch...)
registeredServers, err := source.Parse(cfgSource.Prefix)
if err != nil {
if len(registeredServers) == 0 {

View File

@ -7,7 +7,6 @@ import (
"fmt"
"math/rand"
"os"
"os/signal"
"sync"
"github.com/facebookgo/pidfile"
@ -16,7 +15,7 @@ import (
)
const (
AppVersion = "2.0.31"
AppVersion = "2.0.29-beta.3"
DefaultConfigFileName = "dnscrypt-proxy.toml"
)
@ -24,7 +23,6 @@ type App struct {
wg sync.WaitGroup
quit chan struct{}
proxy *Proxy
flags *ConfigFlags
}
func main() {
@ -46,33 +44,7 @@ func main() {
WorkingDirectory: pwd,
}
svcFlag := flag.String("service", "", fmt.Sprintf("Control the system service: %q", service.ControlAction))
version := flag.Bool("version", false, "print current proxy version")
resolve := flag.String("resolve", "", "resolve a name using system libraries")
flags := ConfigFlags{}
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")
flags.JsonOutput = flag.Bool("json", false, "output list as JSON")
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)
}
if resolve != nil && len(*resolve) > 0 {
Resolve(*resolve)
os.Exit(0)
}
app := &App{
quit: make(chan struct{}),
flags: &flags,
}
app := &App{}
svc, err := service.New(app, svcConfig)
if err != nil {
svc = nil
@ -80,6 +52,9 @@ func main() {
}
app.proxy = NewProxy()
_ = ServiceManagerStartNotify()
if err := ConfigLoad(app.proxy, svcFlag); err != nil {
dlog.Fatal(err)
}
if len(*svcFlag) != 0 {
if svc == nil {
dlog.Fatal("Built-in service installation is not supported on this platform")
@ -100,56 +75,43 @@ func main() {
}
return
}
app.wg.Add(1)
if svc != nil {
if err = svc.Run(); err != nil {
dlog.Fatal(err)
}
} else {
if err := ConfigLoad(app.proxy, &flags); err != nil {
dlog.Fatal(err)
}
app.signalWatch()
app.Start(nil)
}
app.wg.Wait()
dlog.Notice("Stopped.")
}
func (app *App) Start(service service.Service) error {
go func() {
if err := ConfigLoad(app.proxy, app.flags); err != nil {
dlog.Fatal(err)
}
if err := app.proxy.InitPluginsGlobals(); err != nil {
dlog.Fatal(err)
}
app.appMain()
}()
if err := app.proxy.InitPluginsGlobals(); err != nil {
dlog.Fatal(err)
}
app.quit = make(chan struct{})
app.wg.Add(1)
if service != nil {
go func() {
app.AppMain()
}()
} else {
app.AppMain()
}
return nil
}
func (app *App) AppMain() {
pidfile.Write()
app.proxy.StartProxy()
<-app.quit
dlog.Notice("Quit signal received...")
app.wg.Done()
}
func (app *App) Stop(service service.Service) error {
if pidFilePath := pidfile.GetPidfilePath(); len(pidFilePath) > 1 {
os.Remove(pidFilePath)
}
dlog.Notice("Quit signal received...")
close(app.quit)
dlog.Notice("Stopped.")
return nil
}
func (app *App) appMain() {
pidfile.Write()
app.proxy.StartProxy(app.quit)
app.wg.Done()
}
func (app *App) signalWatch() {
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt, os.Kill)
go func() {
<-quit
signal.Stop(quit)
close(app.quit)
}()
}

View File

@ -60,7 +60,7 @@ type Proxy struct {
forwardFile string
cloakFile string
pluginsGlobals PluginsGlobals
urlsToPrefetch []*URLToPrefetch
urlsToPrefetch []URLToPrefetch
clientsCount uint32
maxClients uint32
xTransport *XTransport
@ -74,7 +74,7 @@ type Proxy struct {
showCerts bool
}
func (proxy *Proxy) StartProxy(quit <-chan struct{}) {
func (proxy *Proxy) StartProxy() {
proxy.questionSizeEstimator = NewQuestionSizeEstimator()
if _, err := crypto_rand.Read(proxy.proxySecretKey[:]); err != nil {
dlog.Fatal(err)
@ -96,16 +96,12 @@ func (proxy *Proxy) StartProxy(quit <-chan struct{}) {
// if 'userName' is not set, continue as before
if !(len(proxy.userName) > 0) {
udpCloser, err := proxy.udpListenerFromAddr(listenUDPAddr)
if err != nil {
if err := proxy.udpListenerFromAddr(listenUDPAddr); err != nil {
dlog.Fatal(err)
}
tcpCloser, err := proxy.tcpListenerFromAddr(listenTCPAddr)
if err != nil {
if err := proxy.tcpListenerFromAddr(listenTCPAddr); err != nil {
dlog.Fatal(err)
}
defer udpCloser.Close()
defer tcpCloser.Close()
} else {
// if 'userName' is set and we are the parent process
if !proxy.child {
@ -160,11 +156,9 @@ func (proxy *Proxy) StartProxy(quit <-chan struct{}) {
if len(proxy.userName) > 0 && !proxy.child {
proxy.dropPrivilege(proxy.userName, FileDescriptors)
}
sdc, err := proxy.SystemDListeners()
if err != nil {
if err := proxy.SystemDListeners(); err != nil {
dlog.Fatal(err)
}
defer sdc.Close()
liveServers, err := proxy.serversInfo.refresh(proxy)
if liveServers > 0 {
proxy.certIgnoreTimestamp = false
@ -183,7 +177,7 @@ func (proxy *Proxy) StartProxy(quit <-chan struct{}) {
dlog.Error(err)
dlog.Notice("dnscrypt-proxy is waiting for at least one server to be reachable")
}
go proxy.prefetcher()
proxy.prefetcher(&proxy.urlsToPrefetch)
if len(proxy.serversInfo.registeredServers) > 0 {
go func() {
for {
@ -199,27 +193,30 @@ func (proxy *Proxy) StartProxy(quit <-chan struct{}) {
}
}()
}
<-quit
}
func (proxy *Proxy) prefetcher() {
for {
now := time.Now()
for _, urlToPrefetch := range proxy.urlsToPrefetch {
if now.After(urlToPrefetch.when) {
dlog.Debugf("Prefetching [%s]", urlToPrefetch.url)
if err := PrefetchSourceURL(proxy.xTransport, urlToPrefetch); err != nil {
dlog.Debugf("Prefetching [%s] failed: %s", urlToPrefetch.url, err)
} else {
dlog.Debugf("Prefetching [%s] succeeded. Next refresh scheduled for %v", urlToPrefetch.url, urlToPrefetch.when)
func (proxy *Proxy) prefetcher(urlsToPrefetch *[]URLToPrefetch) {
go func() {
for {
now := time.Now()
for i := range *urlsToPrefetch {
urlToPrefetch := &(*urlsToPrefetch)[i]
if now.After(urlToPrefetch.when) {
dlog.Debugf("Prefetching [%s]", urlToPrefetch.url)
if err := PrefetchSourceURL(proxy.xTransport, urlToPrefetch); err != nil {
dlog.Debugf("Prefetching [%s] failed: %s", urlToPrefetch.url, err)
} else {
dlog.Debugf("Prefetching [%s] succeeded. Next refresh scheduled for %v", urlToPrefetch.url, urlToPrefetch.when)
}
}
}
clocksmith.Sleep(60 * time.Second)
}
clocksmith.Sleep(60 * time.Second)
}
}()
}
func (proxy *Proxy) udpListener(clientPc *net.UDPConn) {
defer clientPc.Close()
for {
buffer := make([]byte, MaxDNSPacketSize-1)
length, clientAddr, err := clientPc.ReadFrom(buffer)
@ -239,17 +236,18 @@ func (proxy *Proxy) udpListener(clientPc *net.UDPConn) {
}
}
func (proxy *Proxy) udpListenerFromAddr(listenAddr *net.UDPAddr) (io.Closer, error) {
func (proxy *Proxy) udpListenerFromAddr(listenAddr *net.UDPAddr) error {
clientPc, err := net.ListenUDP("udp", listenAddr)
if err != nil {
return nil, err
return err
}
dlog.Noticef("Now listening to %v [UDP]", listenAddr)
go proxy.udpListener(clientPc)
return clientPc, nil
return nil
}
func (proxy *Proxy) tcpListener(acceptPc *net.TCPListener) {
defer acceptPc.Close()
for {
clientPc, err := acceptPc.Accept()
if err != nil {
@ -274,14 +272,14 @@ func (proxy *Proxy) tcpListener(acceptPc *net.TCPListener) {
}
}
func (proxy *Proxy) tcpListenerFromAddr(listenAddr *net.TCPAddr) (io.Closer, error) {
func (proxy *Proxy) tcpListenerFromAddr(listenAddr *net.TCPAddr) error {
acceptPc, err := net.ListenTCP("tcp", listenAddr)
if err != nil {
return nil, err
return err
}
dlog.Noticef("Now listening to %v [TCP]", listenAddr)
go proxy.tcpListener(acceptPc)
return acceptPc, nil
return nil
}
func (proxy *Proxy) prepareForRelay(ip net.IP, port int, encryptedQuery *[]byte) {
@ -416,7 +414,7 @@ func (proxy *Proxy) processIncomingQuery(serverInfo *ServerInfo, clientProto str
response, err = proxy.exchangeWithUDPServer(serverInfo, sharedKey, encryptedQuery, clientNonce)
if err == nil && len(response) >= MinDNSPacketSize && response[2]&0x02 == 0x02 {
serverProto = "tcp"
sharedKey, encryptedQuery, clientNonce, err = proxy.Encrypt(serverInfo, query, serverProto)
sharedKey, encryptedQuery, clientNonce, err := proxy.Encrypt(serverInfo, query, serverProto)
if err != nil {
pluginsState.returnCode = PluginsReturnCodeParseError
return

View File

@ -32,6 +32,7 @@ type RegisteredServer struct {
}
type ServerInfo struct {
sync.RWMutex
Proto stamps.StampProtoType
MagicQuery [8]byte
ServerPk [32]byte
@ -157,7 +158,6 @@ func (serversInfo *ServersInfo) refresh(proxy *Proxy) (int, error) {
}
func (serversInfo *ServersInfo) estimatorUpdate() {
// serversInfo.RWMutex is assumed to be Locked
candidate := rand.Intn(len(serversInfo.inner))
if candidate == 0 {
return
@ -191,9 +191,9 @@ func (serversInfo *ServersInfo) estimatorUpdate() {
func (serversInfo *ServersInfo) getOne() *ServerInfo {
serversInfo.Lock()
defer serversInfo.Unlock()
serversCount := len(serversInfo.inner)
if serversCount <= 0 {
serversInfo.Unlock()
return nil
}
if serversInfo.lbEstimator {
@ -211,6 +211,7 @@ func (serversInfo *ServersInfo) getOne() *ServerInfo {
candidate = rand.Intn(Min(serversCount, 2))
}
serverInfo := serversInfo.inner[candidate]
serversInfo.Unlock()
dlog.Debugf("Using candidate [%s] RTT: %d", (*serverInfo).Name, int((*serverInfo).rtt.Value()))
return serverInfo
@ -414,24 +415,24 @@ func fetchDoHServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp, isN
}
func (serverInfo *ServerInfo) noticeFailure(proxy *Proxy) {
proxy.serversInfo.Lock()
serverInfo.Lock()
serverInfo.rtt.Add(float64(proxy.timeout.Nanoseconds() / 1000000))
proxy.serversInfo.Unlock()
serverInfo.Unlock()
}
func (serverInfo *ServerInfo) noticeBegin(proxy *Proxy) {
proxy.serversInfo.Lock()
serverInfo.Lock()
serverInfo.lastActionTS = time.Now()
proxy.serversInfo.Unlock()
serverInfo.Unlock()
}
func (serverInfo *ServerInfo) noticeSuccess(proxy *Proxy) {
now := time.Now()
proxy.serversInfo.Lock()
serverInfo.Lock()
elapsed := now.Sub(serverInfo.lastActionTS)
elapsedMs := elapsed.Nanoseconds() / 1000000
if elapsedMs > 0 && elapsed < proxy.timeout {
serverInfo.rtt.Add(float64(elapsedMs))
}
proxy.serversInfo.Unlock()
serverInfo.Unlock()
}

View File

@ -127,19 +127,19 @@ type URLToPrefetch struct {
when time.Time
}
func NewSource(xTransport *XTransport, urls []string, minisignKeyStr string, cacheFile string, formatStr string, refreshDelay time.Duration) (Source, []*URLToPrefetch, error) {
urlsToPrefetch := []*URLToPrefetch{}
func NewSource(xTransport *XTransport, urls []string, minisignKeyStr string, cacheFile string, formatStr string, refreshDelay time.Duration) (Source, []URLToPrefetch, error) {
source := Source{urls: urls}
if formatStr == "v2" {
source.format = SourceFormatV2
} else {
return source, urlsToPrefetch, fmt.Errorf("Unsupported source format: [%s]", formatStr)
return source, []URLToPrefetch{}, fmt.Errorf("Unsupported source format: [%s]", formatStr)
}
minisignKey, err := minisign.NewPublicKey(minisignKeyStr)
if err != nil {
return source, urlsToPrefetch, err
return source, []URLToPrefetch{}, err
}
now := time.Now()
urlsToPrefetch := []URLToPrefetch{}
sigCacheFile := cacheFile + ".minisig"
var sigStr, in string
@ -166,8 +166,8 @@ func NewSource(xTransport *XTransport, urls []string, minisignKeyStr string, cac
if len(preloadURL) > 0 {
url := preloadURL
sigURL := url + ".minisig"
urlsToPrefetch = append(urlsToPrefetch, &URLToPrefetch{url: url, cacheFile: cacheFile, when: now.Add(delayTillNextUpdate)})
urlsToPrefetch = append(urlsToPrefetch, &URLToPrefetch{url: sigURL, cacheFile: sigCacheFile, when: now.Add(sigDelayTillNextUpdate)})
urlsToPrefetch = append(urlsToPrefetch, URLToPrefetch{url: url, cacheFile: cacheFile, when: now.Add(delayTillNextUpdate)})
urlsToPrefetch = append(urlsToPrefetch, URLToPrefetch{url: sigURL, cacheFile: sigCacheFile, when: now.Add(sigDelayTillNextUpdate)})
}
if sigErr != nil && err == nil {
err = sigErr

View File

@ -1,12 +1,5 @@
// +build android
package main
import (
"io"
"io/ioutil"
)
func (proxy *Proxy) SystemDListeners() (io.Closer, error) {
return ioutil.NopCloser(nil), nil
func (proxy *Proxy) SystemDListeners() error {
return nil
}

View File

@ -2,11 +2,6 @@
package main
import (
"io"
"io/ioutil"
)
func (proxy *Proxy) SystemDListeners() (io.Closer, error) {
return ioutil.NopCloser(nil), nil
func (proxy *Proxy) SystemDListeners() error {
return nil
}

View File

@ -4,23 +4,13 @@ package main
import (
"fmt"
"io"
"net"
"github.com/coreos/go-systemd/activation"
"github.com/jedisct1/dlog"
)
type multiCloser []io.Closer
func (mc multiCloser) Close() (err error) {
for _, c := range mc {
err = c.Close()
}
return err
}
func (proxy *Proxy) SystemDListeners() (io.Closer, error) {
func (proxy *Proxy) SystemDListeners() error {
files := activation.Files(true)
if len(files) > 0 {
@ -29,25 +19,22 @@ func (proxy *Proxy) SystemDListeners() (io.Closer, error) {
}
dlog.Warn("Systemd sockets are untested and unsupported - use at your own risk")
}
var mc multiCloser
for i, file := range files {
defer file.Close()
ok := false
if listener, err := net.FileListener(file); err == nil {
dlog.Noticef("Wiring systemd TCP socket #%d, %s, %s", i, file.Name(), listener.Addr())
ok = true
mc = append(mc, listener)
go proxy.tcpListener(listener.(*net.TCPListener))
} else if pc, err := net.FilePacketConn(file); err == nil {
dlog.Noticef("Wiring systemd UDP socket #%d, %s, %s", i, file.Name(), pc.LocalAddr())
ok = true
mc = append(mc, pc)
go proxy.udpListener(pc.(*net.UDPConn))
}
if !ok {
return nil, fmt.Errorf("Could not wire systemd socket #%d, %s", i, file.Name())
return fmt.Errorf("Could not wire systemd socket #%d, %s", i, file.Name())
}
}
return mc, nil
return nil
}

View File

@ -133,11 +133,7 @@ func (xTransport *XTransport) rebuildTransport() {
ipOnly := host
cachedIP, ok := xTransport.loadCachedIP(host, false)
if ok {
if ipv4 := cachedIP.To4(); ipv4 != nil {
ipOnly = ipv4.String()
} else {
ipOnly = "[" + cachedIP.String() + "]"
}
ipOnly = cachedIP.String()
} else {
dlog.Debugf("[%s] IP address was not cached", host)
}